Har*_*riv 12 delphi multithreading splash-screen delphi-2007
我想在加载应用程序时显示启动画面.但是,某些第三方组件在启动期间会阻塞主线程几秒钟,这会导致所有表单都不更新.是否可以使用自己的线程启动屏幕,这样当主线程忙时它也会更新?
该应用程序是win32和Delphi 2007版.
编辑:我正在尝试避免"未绘制的启动画面"效果,如果某些其他窗口(来自其他应用程序)位于启动画面的顶部,例如alt-tabbing到另一个应用程序并返回,则会发生这种情况.
您可以在另一个线程中运行启动屏幕,但随后您将需要使用原始Windows API调用或实现类似VCL类的第三方库(如密钥对象库).但是,不要从启动线程访问VCL内容.
如果你走这条路线(我认为你不应该这样做,因为这是一项很少有收获的工作),请务必遵守多线程的Windows API访问规则.谷歌例如为"用户界面线程"提供更多信息.
编辑:
我以前没有意识到这一点,但实际上有一个组件在CodeCentral上为Delphi实现了Threaded Splashscreen.使用这个组件它可能(没有尝试过)实际上很容易将启动画面放在不同的线程中,但是对辅助线程的VCL访问的警告仍然存在.
其实 WinApi 的方式很简单,只要你使用对话框资源。检查这个(即使在 D7 和 XP 上也能工作):
type
TDlgThread = class(TThread)
private
FDlgWnd: HWND;
FCaption: string;
protected
procedure Execute; override;
procedure ShowSplash;
public
constructor Create(const Caption: string);
end;
{ TDlgThread }
// Create thread for splash dialog with custom Caption and show the dialog
constructor TDlgThread.Create(const Caption: string);
begin
FCaption := Caption;
inherited Create(False);
FreeOnTerminate := True;
end;
procedure TDlgThread.Execute;
var Msg: TMsg;
begin
ShowSplash;
// Process window messages until the thread is finished
while not Terminated and GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
EndDialog(FDlgWnd, 0);
end;
procedure TDlgThread.ShowSplash;
const
PBM_SETMARQUEE = WM_USER + 10;
{$I 'Dlg.inc'}
begin
FDlgWnd := CreateDialogParam(HInstance, MakeIntResource(IDD_WAITDLG), 0, nil, 0);
if FDlgWnd = 0 then Exit;
SetDlgItemText(FDlgWnd, IDC_LABEL, PChar(FCaption)); // set caption
SendDlgItemMessage(FDlgWnd, IDC_PGB, PBM_SETMARQUEE, 1, 100); // start marquee
end;
procedure TForm1.Button3Click(Sender: TObject);
var th: TDlgThread;
begin
th := TDlgThread.Create('Connecting to DB...');
Sleep(3000); // blocking wait
th.Terminate;
end;
Run Code Online (Sandbox Code Playgroud)
当然,您必须准备对话资源 ( Dlg.rc) 并将其添加到您的项目中:
#define IDD_WAITDLG 1000
#define IDC_PGB 1002
#define IDC_LABEL 1003
#define PBS_SMOOTH 0x00000001
#define PBS_MARQUEE 0x00000008
IDD_WAITDLG DIALOGEX 10,10,162,33
STYLE WS_POPUP|WS_VISIBLE|WS_DLGFRAME|DS_CENTER
EXSTYLE WS_EX_TOPMOST
BEGIN
CONTROL "",IDC_PGB,"msctls_progress32",WS_CHILDWINDOW|WS_VISIBLE|PBS_SMOOTH|PBS_MARQUEE,9,15,144,15
CONTROL "",IDC_LABEL,"Static",WS_CHILDWINDOW|WS_VISIBLE,9,3,144,9
END
Run Code Online (Sandbox Code Playgroud)
注意这些PBS_*定义。我不得不添加它们,因为 Delphi 7 对这些常量一无所知。和常量的定义 ( Dlg.inc)
const IDD_WAITDLG = 1000;
const IDC_PGB = 1002;
const IDC_LABEL = 1003;
Run Code Online (Sandbox Code Playgroud)
(我使用自动生成包含文件的 RadAsm 资源编辑器)。
与 VCL 技巧(表单创建顺序等)相比,这种方式更好的是,当您的应用程序需要一些时间思考时,您可以多次使用它。
| 归档时间: |
|
| 查看次数: |
10824 次 |
| 最近记录: |