代码之家  ›  专栏  ›  技术社区  ›  Ken White

Peter Below的线程式启动屏幕和模式对话框

  •  0
  • Ken White  · 技术社区  · 16 年前

    我在用 Peter Below's PBThreadedSplashForm 在应用程序启动期间显示。在创建数据模块期间(刚好在创建主窗体之前)打开各种数据库时,它会得到更新。

    问题是,我们检查了在创建数据模块期间所做的某些事情的存在性。如果缺少这些项中的任何一项,将显示一个模式对话框,以便可以创建该项或关闭应用程序。(缺少的项通常是索引,当我们重新索引数据库时,主要使用对话框,因此它针对的是开发人员而不是普通用户。)但是,模式对话框显示在初始屏幕后面;当标题更改时,它似乎是焦点窗口,但显示在初始屏幕后面。

    启动屏幕是使用Windows API CreateWindowEx()从与主进程不同的线程创建的,使用以下代码:

    procedure TPBSplashThread.CreateSplashWindow;
    const
      TopmostStyle: Array [Boolean] of DWORD = (0, WS_EX_TOPMOST );
      NoActivateStyle : Array [Boolean] of DWORD = (0, WS_EX_NOACTIVATE );
    var
      wsize: TSize;
    begin
      wsize.cx := FSurface.Width + GetSystemMetrics( SM_CXEDGE ) * 2;
      wsize.cy := FSurface.Height + GetSystemMetrics( SM_CYEDGE ) * 2;
      FWnd := CreateWindowEx(
                TopmostStyle[ FTopmost ] or WS_EX_TOOLWINDOW
                or WS_EX_STATICEDGE or WS_EX_CLIENTEDGE
                or NoActivateStyle[ Win32MajorVersion >= 5 ],
                MakeIntResource( FWndClass ),
                nil,
                WS_POPUP or WS_BORDER,
                Forigin.x, Forigin.y,
                wsize.cx, wsize.cy,
                0, 0, hInstance, self );
      If FWnd = 0 Then
        raise exception.create('TPBSplashThread.CreateSplashWindow: CreateWindowEx failed');
    end;
    

    ftopmost是一个从未设置过的属性(具有明显的含义),因此由于类构造期间的默认初始化,它是错误的。(我还尝试显式地将其设置为false,以防万一,没有效果。)我还尝试在模式对话框的OnShow事件期间使用setForegroundWindow()和setWindowPos(),但没有效果。

    有人知道这可能是什么原因吗?

    3 回复  |  直到 16 年前
        1
  •  3
  •   Ken White    16 年前

    好啊。终于解决了这个问题。它似乎是由调用CreateWindowEx()时的WS-Ex-NoActivate标志引起的。将其更改为“删除”似乎可以解决问题;模式对话框显示在初始屏幕上方,并且由于它是模式,因此初始屏幕无法置于其上方。

    工作代码为:

    
      FWnd := CreateWindowEx(
                TopmostStyle[ FTopmost ] or WS_EX_TOOLWINDOW
                or WS_EX_STATICEDGE or WS_EX_CLIENTEDGE,
                MakeIntResource( FWndClass ),
                nil,
                WS_POPUP or WS_BORDER,
                Forigin.x, Forigin.y,
                wsize.cx, wsize.cy,
                0, 0, hInstance, self );
    

    罗布和克雷格,谢谢你的努力。

        2
  •  0
  •   Rob Kennedy    16 年前

    如果你想找个解释,我帮不了你。

    如果你在寻找解决方案,你不是第一个。 Eddie Shipman encountered this same problem in May. 他提出的解决方案是使另一个对话框(被闪屏隐藏的对话框)成为最顶部的窗口,但他最终通过在应用程序需要显示任何其他窗口之前隐藏闪屏来避免这个问题。

    另一个建议是在启动屏幕上发布命令, 显示消息框。该对话框可以作为初始屏幕的父级。不过,这很棘手,因为你再也不能享受到录像机的任何奢侈品了,因为它在主线之外不起作用。

        3
  •  0
  •   Zoë Peterson RRUZ    16 年前

    您应该能够通过将对话框设置为启动屏幕的父级来解决这个问题。将初始屏幕的hwnd分配给全局变量,并重写对话框的createParams方法。如果全局hwnd具有值,请将其分配给createParams传入的params.wndParent变量。事实上,它们来自不同的线程并不重要,因为它只处理HWND,而不是VCL对象,Windows将处理同步。