我试图在我的进程正在进行时显示进度条...在我的应用程序中,会出现一种情况,我必须读取文件并操作它们(需要一些时间才能完成)..想要显示在此操作期间出现进度条..我调用的特定函数是 win 32 ...所以如果您检查下面的代码,我已经可以在对话框窗口中创建进度条并创建线程了,现在我不知道如何发布消息以及在哪里获取消息并处理...请帮助我..提前致谢
//my function
int Myfunction(....)
{
MSG msg;
HWND dialog = CreateWindowEx(0,WC_DIALOG,L"Proccessing...",WS_OVERLAPPEDWINDOW|WS_VISIBLE,
600,300,280,120,NULL,NULL,NULL,NULL);
HWND pBar = CreateWindowEx(NULL,PROGRESS_CLASS,NULL,WS_CHILD|WS_VISIBLE,40,20,200, 20,
dialog,(HMENU)IDD_PROGRESS,NULL,NULL);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
Dispatch(&message);
}
SendMessage(pBar,PBM_SETRANGE,0,MAKELPARAM(0,noOfFile));
HANDLE getHandle = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)SetFilesForOperation(...),
NULL,NULL,0);
}
LPARAM SetFilesForOperation(...)
{
for(int index = 0;index < noOfFiles; index++)
{
*checkstate = *(checkState + index);
if(*checkstate == -1)
{
*(getFiles+i) = new TCHAR[MAX_PATH];
wcscpy(*(getFiles+i),*(dataFiles +index));
i++;
}
else
{
(*tempDataFiles)->Add(*(dataFiles+index));
*(checkState + localIndex) = *(checkState + index);
localIndex++;
}
PostMessage(pBar,PBM_SETPOS,(WPARAM)index,0);
}
}
编辑2: 使用 AFXTHREAD
//instead of createthread i used AfxBegin thread
ptrThread = AfxBeginThread((AFX_THREADPROC)SetFilesForOperation(pBar,checkstate,checkState,noOfFiles,i,getFilesforcompression,dataFiles,&tempDataFiles,localIndex),
NULL,THREAD_PRIORITY_ABOVE_NORMAL,NULL,NULL,NULL);
for(int index = 0;index < noOfFiles; index++)
{
MSG msg;
*checkstate = *(checkState + index);
if(*checkstate == -1)
{
*(getFilesforcompression+i) = new TCHAR[MAX_PATH];
//*(getFilesforcompression+i) = L"C:\\Documents and Settings\\rakesh\\Desktop\\try2_Extracted";
wcscpy(*(getFilesforcompression+i),*(dataFiles +index));
i++;
}
else
{
(*tempDataFiles)->Add(*(dataFiles+index));
*(checkState + localIndex) = *(checkState + index);
localIndex++;
}
//PostMessage( pBar, PBM_SETPOS, (WPARAM)index, 0 );
PostMessage( pBar, PBM_SETRANGE, 0, MAKELPARAM( 0, noOfFiles ) );
//PostMessage( pBar, PBM_SETPOS, (WPARAM)index, 0 );
PostMessage( pBar, PBM_STEPIT, (WPARAM)index, 0 );
PostMessage( pBar, MSG_PROGRESS_VALUE, 0, 0 );
while(1)
{
while(PeekMessage( &msg, NULL, NULL, NULL, PM_NOREMOVE))
{
AfxGetThread()->PumpMessage();
Sleep(10);
}
最佳答案
跨线程发送消息时存在一些问题。如果您从线程 A 向线程 B 发送消息,那么内部发生的事情是线程 A 将消息发布到线程 B 的消息队列。然后,它会等待消息被处理,然后再将结果发送回线程 A。这意味着您需要在线程 B 中泵送消息,否则线程 A 将死锁。
对于您的具体问题,您可以在创建进度条后简单地添加以下代码:
SendMessage( pBar, PBM_SETRANGE, 0, MAKELPARAM( 0, noOfFiles ) );
然后您需要将 pBar 传递到您的线程中。这很容易。您会注意到,CreateThread 允许您将参数作为 void* 传递给线程函数。因此,将您的 CreateThread 重写为:
HANDLE getHandle = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)SetFilesForOperation(...),
(void*)pBar,NULL,0);
然后将您的 SetFilesForOperation 原型(prototype)更改为:
LPARAM SetFilesForOperation( HWND pBar );
请注意,您将线程函数转换为正确的格式。因此,Windows 在内部只会传递 void*。然后发生隐式转换,您在另一端看到的是 HWND 而不是 void*。您可以通过将指向结构的指针传递给线程函数来传递更多数据。请记住,在 SetFilesForOperation 从中获取所需信息之前,不要释放该结构(无论是让它超出范围还是显式地释放)。您可以通过一个简单的事件来解决此问题,一旦线程函数获得其所在的数据,该事件就会被触发,然后在创建要触发的事件的线程中等待。
然后只需在循环末尾添加以下消息:
PostMessage( pBar, PBM_SETPOS, (WPARAM)index, 0 );
每次循环都会将条形推进一。
编辑:正如评论中所指出的,使用 PostMessage 是值得的,因为它不会等待返回,这意味着消息只是发布到 UI 线程的消息队列中。但请注意,如果您不泵送该消息队列,您将发送消息,并且您不会看到进度条更新,因为消息只会备份在队列中。
编辑2:您正在消息循环之后设置进度条的范围。所以范围永远不会被设定。您需要事先这样做。还值得注意的是,只有当您发送 WM_QUIT 消息时,您的消息泵才会退出。这并不理想。您可以在线程循环的末尾发布您自己的消息。您需要的更改如下。首先,您需要声明自定义(用户)消息。
#define WM_EXITTHREAD WM_USER + 1
然后将消息循环更改为以下内容:
SendMessage(pBar,PBM_SETRANGE,0,MAKELPARAM(0,noOfFile));
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
if ( msg.message == WM_EXITTHREAD )
{
break;
}
TranslateMessage(&msg);
Dispatch(&msg);
}
最后在线程末尾添加以下内容:
PostMessage( pBar, WM_EXITTHREAD, 0, 0 );
EndThread( 0 ); // This is the preferred way of exiting a thread in C
return 0; // This is the preferred way of exiting a thread in C++ so that destructors get called.
Edit3:如果您使用这样的 peek 消息循环会发生什么?
while( 1 )
{
MSG msg;
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_EXITTHREAD )
{
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Sleep( 0 );
}
}
关于c - 如何在 win 32 中使用线程概念实现进度条(显示进度)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2552101/