我正在使用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。 (我也尝试将其明确设置为False,以防万一,没有效果。)我也尝试在模态对话框的OnShow事件中使用SetForegroundWindow()和SetWindowPos(),但没有效果。
有谁知道可能导致这种情况的原因是什么?
答案 0 :(得分:3)
确定。终于解决了问题。它似乎是由对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 );
谢谢Rob和Craig的努力。
答案 1 :(得分:0)
如果您正在寻找解释,我无法帮助您。
如果您正在寻找解决方案,那么您不是第一个。 Eddie Shipman encountered this same problem in May.他提出的解决办法是让另一个对话框(闪屏隐藏的对话框)成为最顶层的窗口,但他最终通过在应用程序显示任何其他窗口之前隐藏启动画面来避免此问题。 / p>
另一个建议是将命令发布到启动画面并让它显示消息框。该对话框可以作为启动画面的父级。不过,这很棘手,因为你不再提供VCL的任何奢侈品,因为它不能在主线之外工作。
答案 2 :(得分:0)
您应该可以通过将对话框设置为启动画面来解决此问题。将启动屏幕的HWND分配给全局变量,并覆盖对话框的CreateParams方法。如果全局HWND有一个值,则将其分配给CreateParams传入的Params.WndParent变量。事实上,它们来自不同的线程并不重要,因为它只是处理HWND,而不是VCL对象,Windows将处理同步。