4

タッチスクリーン PC で実行されているアプリケーションのシステム スクロールバーのサイズを拡大するコードがあります。このコードは Delphi 7 で書かれており、数年間問題なく動作していますが、Windows 7 で実行すると問題があるようです。

コードは次のようになります。

procedure SetLargeScrollBars();
type
    // Extended NONCLIENTMETRICS structure not defined in Delphi 7's Windows.pas
    tagNONCLIENTMETRICSXA = packed record
        cbSize: UINT;
        iBorderWidth: Integer;
        iScrollWidth: Integer;
        iScrollHeight: Integer;
        iCaptionWidth: Integer;
        iCaptionHeight: Integer;
        lfCaptionFont: TLogFontA;
        iSmCaptionWidth: Integer;
        iSmCaptionHeight: Integer;
        lfSmCaptionFont: TLogFontA;
        iMenuWidth: Integer;
        iMenuHeight: Integer;
        lfMenuFont: TLogFontA;
        lfStatusFont: TLogFontA;
        lfMessageFont: TLogFontA;
        // This member not supported for Windows Server 2003 and Windows XP/2000
        iPaddedBorderWidth: Integer;
    end;
    NONCLIENTMETRICSX = tagNONCLIENTMETRICSXA;
var
    ncm: NONCLIENTMETRICSX;
    osvi: OSVERSIONINFO;
const
    LARGE_SCROLL_DIM = 48;
begin
    // Zero the NONCLIENTMETRICS type and fill in its size
    ZeroMemory(@ncm, Sizeof(ncm));
    ncm.cbSize := SizeOf(ncm);

    // This is necessary because SystemParametersInfo works differently for 
    // Windows Server 2008, Windows Vista and after.
    ZeroMemory(@osvi, SizeOf(osvi));
    osvi.dwOSVersionInfoSize := SizeOf(osvi);
    GetVersionEx(osvi);

    if (osvi.dwMajorVersion < 6) then
    begin
        ncm.cbSize := ncm.cbSize - SizeOf(ncm.iPaddedBorderWidth);
    end;

    // Seems to return true all the time.
    SystemParametersInfo(
        SPI_GETNONCLIENTMETRICS,
        Sizeof(ncm),
        @ncm,
        0);

    if (ncm.iScrollWidth <> LARGE_SCROLL_DIM) then
    begin
        // Save the scrollbar width and height for restoration when the application closes.
        m_ScrollWidth := ncm.iScrollWidth;
        m_ScrollHeight := ncm.iScrollHeight;

        ncm.iScrollWidth := LARGE_SCROLL_DIM;
        ncm.iScrollHeight := LARGE_SCROLL_DIM;

        // This call never returns...
        SystemParametersInfo(
            SPI_SETNONCLIENTMETRICS,
            Sizeof(ncm),
            @ncm,
            SPIF_SENDCHANGE);
    end;
end;

興味深いのは、スクロールバーのサイズが実際に設定されていることです。そのため、SystemParametersInfo は本来の処理を行っているように見えますが、その後は混乱しているように見えます。

スクロールバーが既に展開されているかどうかのチェック機能があるため、2 回目以降は問題なく動作します (テーマを元に戻してスクロールバーをリセットしない限り)。

最後のパラメーター (fWinIni) と関係があるのではないかと思っていたので、ゼロを含むさまざまな値をすべて試しましたが、役に立ちませんでした。

おそらく、設定が変更された後、Windows 7 は以前のフレーバーの OS とは何か違うことをするのでしょうか? とは言っても、Vistaでは試していないので、同じことが起こるかもしれません。これは、Windows Vista、Windows Server 2008、およびそれ以降のバージョンの iPaddedBorderWidth の追加に関連している可能性があります - NONCLIENTMETRICS 構造を参照してください

.NET の観点から見た同じ状況に関するMSDN Problem Changing size of scrollbars using SystemParametersInfo(SPI_SETNONCLIENTMETRICS)に同様の質問がありますが、これまでのところ回答はありません。


さらに詳しい情報

関連するアプリケーションでハング分析を実行するために DebugDiag を使用したところ、次のスタック トレースが表示されました。

関数
ntdll!KiFastSystemCallRet
uxtheme!Ordinal45+25d
uxtheme!BeginBufferedAnimation+25b
user32!SystemParametersInfoA+40
プログラム名+13024f
プログラム名+117c8d
プログラム名+6ae72 プログラム
名+727dc プログラム
名+132645
kernel32!BaseThreadInitThunk+12
ntdll!RtlInitializeExceptionChain+tInitializeExceptionChain+ef
ntdll

したがって、ハングが uxtheme!Ordinal45+25d で発生しているように見えます - おそらく何らかのシステム コールで発生しています。

4

1 に答える 1

9

別のウィンドウが原因で問題が発生している可能性があります。- パラメータで呼び出しSystemParametersInfoていSPIF_SENDCHANGEます。これにより、WM_SETTINGSCHANGEメッセージが でブロードキャストされSendMessageます。このメッセージに応答しないウィンドウがある場合、への呼び出しSystemParametersInfoはハングします。The Old New Thing のこのエントリをお読みください。

于 2014-07-03T13:55:05.040 に答える