【发布时间】:2019-05-05 16:35:45
【问题描述】:
我用 C++ 创建了一个简单的 Windows 控制台程序,它执行一些处理和一个带有进度条的窗口,该进度条会随着处理的进行而更新。问题是进度条没有更新。
下面是我的示例应用程序的代码。
#include <iostream>
#include <stdlib.h>
#include "atlstr.h"
#include "pch.h"
#include <string.h>
#include "tchar.h"
#include <vector>
#define ISOLATION_AWARE_ENABLED 1
#include <windows.h>
#include <commctrl.h>
using namespace std;
#define WM_UPDATEPROGRESS WM_USER + 1
typedef struct {
HWND window;
HWND hwndPB;
} OPERATION_INFO;
void DoOperation(LPVOID lpThreadParams) {
//reading ThreadParams
OPERATION_INFO *pOperationInfo = (OPERATION_INFO *)lpThreadParams;
//run a test loop that updates bar
for (int i = 1; i <= 10; i += 1) {
// do something
Sleep(500); // dummily waiting some time
// send message to update progress bar
PostMessage(
pOperationInfo->window, WM_UPDATEPROGRESS, 0, NULL);
}
}
LONG_PTR CALLBACK WindowProcedure(
HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
RECT rcClient;
HWND hwndPB = NULL;
OPERATION_INFO operationInfo;
static bool flag_activate = FALSE;
switch (msg)
{
case WM_CREATE:
// create progress bar
GetClientRect(window, &rcClient);
hwndPB = CreateWindowEx(0, PROGRESS_CLASS,
(LPCWSTR)NULL, (WS_CHILD | WS_VISIBLE),
20,
20,
rcClient.right - rcClient.left - 40,
20,
window, (HMENU)0, GetModuleHandle(0), NULL);
// progress bar settings
SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
SendMessage(hwndPB, PBM_SETPOS, (WPARAM)0, 0);
SendMessage(hwndPB, PBM_SETSTEP, (WPARAM)10, 0);
case WM_ACTIVATEAPP:
// if message already fired then do nothing:
// because in this message we have code to initialize thread
// that updates progress bar and the thread initialization,
// obviously, must be done once.
if (flag_activate)
break;
else
{
// store message MW_ACTIVEAPP fired
flag_activate = TRUE;
// initialize thread
OPERATION_INFO operationInfo = { window, hwndPB };
HANDLE threadHandle;
// make thread call DoOperation routine
threadHandle = CreateThread(
NULL, 0,
(LPTHREAD_START_ROUTINE)DoOperation,
(LPVOID)&operationInfo, 0, 0);
}
break;
case WM_UPDATEPROGRESS:
//get info with HWND of the progress bar to update
//update the progress bar
SendMessage(hwndPB, PBM_STEPIT, NULL, 0);
//release memory
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0L;
case WM_LBUTTONDOWN:
break;
default:
return DefWindowProc(window, msg, wp, lp);
}
}
int main()
{
// Window creation
// structure initialization
LPCWSTR myclass = L"myclass";
WNDCLASSEX wndclass = {
sizeof(WNDCLASSEX), CS_DBLCLKS,
WindowProcedure, 0, 0, GetModuleHandle(0),
LoadIcon(0,IDI_APPLICATION), LoadCursor(0,IDC_ARROW),
HBRUSH(COLOR_WINDOW + 1), 0, myclass,
LoadIcon(0,IDI_APPLICATION) };
// preliminar action
if (RegisterClassEx(&wndclass))
{
// create window
HWND window = CreateWindowEx(0, myclass, L"Processing",
WS_OVERLAPPED | WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
300, 150,
0, 0, GetModuleHandle(0), 0);
// if OK
if (window)
{
// show window
ShowWindow(window, SW_SHOWDEFAULT);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
}
}
}
我希望进度条每秒更新一次,但这不会发生:进度条什么都不做。
怎么了?
【问题讨论】:
-
警告:如果您使用的是 Visual Studio,您会发现
#include "pch.h"的放置是不必要的或致命的。如果使用了预编译的头文件,#include "pch.h"MUST be the first non-comment in the file。之前的一切都被默默地忽略了。如果未使用预编译的头文件,则无需包含 pch.h。 -
几年前我看到了一个类似的问题:没有代码调用 Invalidate,所以它从来没有调用 Paint,所以它从来没有更新任何东西。 STEPIT 消息是否做了所有必要的事情?
-
hwndPB是一个局部变量。如果您在WM_UPDATEPROGRESS处理程序上设置断点,您会注意到这一点。 -
其他问题包括演员
(LPTHREAD_START_ROUTINE)DoOperation。如果DoOperation有错误的签名,正如编译器告诉你的,你必须修复签名。你的演员只是告诉编译器一个谎言,即你声称DoOperation是LPTHREAD_START_ROUTINE而不是。