加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 为什么SystemParametersInfo(SPI_SETNONCLIENTMETRICS

发布时间:2020-12-15 09:36:24 所属栏目:大数据 来源:网络整理
导读:我有一些代码可以扩展触摸屏PC上运行的应用程序的系统滚动条的大小.这段代码是用Delphi 7编写的,并且已经运行了好几年,但是我发现在 Windows 7上运行时似乎存在问题. 代码如下所示: procedure SetLargeScrollBars();type // Extended NONCLIENTMETRICS stru
我有一些代码可以扩展触摸屏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,SPIF_SENDCHANGE);
    end;
end;

奇怪的是滚动条大小实际上是设置的,所以看起来SystemParametersInfo正在做它应该做的事情,但是在那之后似乎感到困惑.

由于在函数中检查滚动条是否已经展开,因此应用程序第二次及其后运行正常(除非通过将主题恢复为原始状态来重置滚动条).

我想知道它是否与最后一个参数(fWinIni)有关,并尝试了所有各种值,包括零,但无济于事.

在设置更改后,Windows 7可能会与早期版本的操作系统有所不同吗?话虽如此,我还没有在Vista上尝试过,所以也许会发生同样的事情.它可能与为Windows Vista,Windows Server 2008和后续版本添加iPaddedBorderWidth有关 – 请参阅NONCLIENTMETRICS Structure

从.NET的角度来看,MSDN Problem Changing size of scrollbars using SystemParametersInfo(SPI_SETNONCLIENTMETRICS)上存在类似的问题,但到目前为止还没有答案.

更多的信息

我使用DebugDiag对相关应用程序执行挂起分析,它显示以下堆栈跟踪:

Function
ntdll!KiFastSystemCallRet
uxtheme!Ordinal45+25d
uxtheme!BeginBufferedAnimation+25b
user32!SystemParametersInfoA+40
programName+13024f
programName+117c8d
programName+6ae72
programName+727dc
programName+132645
kernel32!BaseThreadInitThunk+12
ntdll!RtlInitializeExceptionChain+ef
ntdll!RtlInitializeExceptionChain+c2

因此看起来好像悬挂发生在uxtheme!Ordinal45 25d – 可能是在某种系统调用中.

解决方法

也许问题是由另一个窗口引起的.您正在使用SPIF_SENDCHANGE参数调用SystemParametersInfo.这会导致使用SendMessage广播WM_SETTINGSCHANGE消息.当有一个窗口不响应此消息时,对SystemParametersInfo的调用将挂起.请阅读The Old New Thing的 this entry.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读