介绍:
某些软件打开后,首先会看到数据载入的进度条,而不是主界面。也就是说,无窗口的后台程序在运行,进度条也在改变。 其实这是通过多线程实现的。
原理:
主程序先创建一个线程,该线程接着创建一个进度条,然后主程序开始后台处理,在后台处理期间不断的给进度条SendMessage,来改变进度。
IDD_DIALOG1 和 IDC_PROGRESS1 是资源中的窗口和进度条的ID。
#include
<
windows.h
>
#include " resource.h "
#include < process.h >
#include < commctrl.h >
#pragma comment (lib, " comctl32.lib " )
#define WM_DLGCREATED WM_USER + 1
// #define WM_PROGRESS WM_USER+2
typedef struct
{
HWND hDlg;
HANDLE hDlgCreatedEvent;
HWND hProgress;
HINSTANCE hInst;
}MyParams, * ptMyParams;
/* ----------------------------------------------------------------------- */
BOOL CALLBACK MyDlgProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
void Thread1(PVOID pvoid);
/* ------------------------------------------------------------------------ */
void Thread1(PVOID pvoid)
{
ptMyParams pt = (ptMyParams)pvoid;
DialogBoxParam(pt -> hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, MyDlgProc, (LPARAM)pt);
_endthread();
}
/* ------------------------------------------------------------------------ */
BOOL CALLBACK MyDlgProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
ptMyParams pt;
switch (Message)
{
case WM_INITDIALOG:
pt = (ptMyParams)lParam;
pt -> hDlg = hWnd;
pt -> hProgress = GetDlgItem(hWnd, IDC_PROGRESS1);
PostMessage(hWnd, WM_DLGCREATED, 0 , lParam);
return TRUE;
case WM_DLGCREATED:
pt = (ptMyParams)lParam;
SetEvent(pt -> hDlgCreatedEvent); // 信号置位(1)
return TRUE;
}
return FALSE;
}
/* ------------------------------------------------------------------------ */
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
static MyParams myParam; // 静态变量
int i;
INITCOMMONCONTROLSEX initcontrols;
initcontrols.dwSize = sizeof(INITCOMMONCONTROLSEX);
initcontrols.dwICC = ICC_PROGRESS_CLASS;
InitCommonControlsEx( & initcontrols);
myParam.hInst = hInstance;
myParam.hDlgCreatedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // 初始化信号(0)
// 传入要使用的变量地址,而不能在另一线程中直接使用全局变量
_beginthread(Thread1, 0 , & myParam);
WaitForSingleObject(myParam.hDlgCreatedEvent, INFINITE); // 等待信号置位(1)
CloseHandle(myParam.hDlgCreatedEvent); // 删除Handle
myParam.hDlgCreatedEvent = 0 ;
SendMessage(myParam.hProgress, PBM_SETRANGE, 0 , MAKELPARAM( 0 , 30 ));
for (i = 0 ;i < 30 ;i ++ )
{
SendMessage(myParam.hProgress, PBM_SETPOS, i, 0 );
Sleep( 50 );
}
Sleep( 500 );
EndDialog(myParam.hDlg, 0 );
return 0 ;
}
#include " resource.h "
#include < process.h >
#include < commctrl.h >
#pragma comment (lib, " comctl32.lib " )
#define WM_DLGCREATED WM_USER + 1
// #define WM_PROGRESS WM_USER+2
typedef struct
{
HWND hDlg;
HANDLE hDlgCreatedEvent;
HWND hProgress;
HINSTANCE hInst;
}MyParams, * ptMyParams;
/* ----------------------------------------------------------------------- */
BOOL CALLBACK MyDlgProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
void Thread1(PVOID pvoid);
/* ------------------------------------------------------------------------ */
void Thread1(PVOID pvoid)
{
ptMyParams pt = (ptMyParams)pvoid;
DialogBoxParam(pt -> hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, MyDlgProc, (LPARAM)pt);
_endthread();
}
/* ------------------------------------------------------------------------ */
BOOL CALLBACK MyDlgProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
ptMyParams pt;
switch (Message)
{
case WM_INITDIALOG:
pt = (ptMyParams)lParam;
pt -> hDlg = hWnd;
pt -> hProgress = GetDlgItem(hWnd, IDC_PROGRESS1);
PostMessage(hWnd, WM_DLGCREATED, 0 , lParam);
return TRUE;
case WM_DLGCREATED:
pt = (ptMyParams)lParam;
SetEvent(pt -> hDlgCreatedEvent); // 信号置位(1)
return TRUE;
}
return FALSE;
}
/* ------------------------------------------------------------------------ */
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
static MyParams myParam; // 静态变量
int i;
INITCOMMONCONTROLSEX initcontrols;
initcontrols.dwSize = sizeof(INITCOMMONCONTROLSEX);
initcontrols.dwICC = ICC_PROGRESS_CLASS;
InitCommonControlsEx( & initcontrols);
myParam.hInst = hInstance;
myParam.hDlgCreatedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // 初始化信号(0)
// 传入要使用的变量地址,而不能在另一线程中直接使用全局变量
_beginthread(Thread1, 0 , & myParam);
WaitForSingleObject(myParam.hDlgCreatedEvent, INFINITE); // 等待信号置位(1)
CloseHandle(myParam.hDlgCreatedEvent); // 删除Handle
myParam.hDlgCreatedEvent = 0 ;
SendMessage(myParam.hProgress, PBM_SETRANGE, 0 , MAKELPARAM( 0 , 30 ));
for (i = 0 ;i < 30 ;i ++ )
{
SendMessage(myParam.hProgress, PBM_SETPOS, i, 0 );
Sleep( 50 );
}
Sleep( 500 );
EndDialog(myParam.hDlg, 0 );
return 0 ;
}
注意:
1. 必须使用信号,待窗口创建之后才能给进度条SendMessage。否则窗口可能无法显示,或出现其它问题。
2. 不能直接在线程中使用全局变量,必须通过参数传递该变量指针。该指针被传给了线程入口函数的参数pvoid。