【问题标题】:Win32 API dialogbox stalls/freezes on moving itWin32 API 对话框在移动时停止/冻结
【发布时间】:2014-01-10 08:15:38
【问题描述】:

我有一个无模式的 Win32 API 对话框作为状态框,其中有一个 LISTBOX,我在其中打印 IDE 和 MSSCCI 提供程序之间通信的一些信息。

除非我作为 IDE 用户触摸状态对话框并尝试移动它,否则一切正常(状态消息逐行打印并滚动)。

然后状态更新冻结(当多次单击状态对话框时,标题栏中会出现“未响应”)以及父应用程序(IDE)。

程序似乎仍在后台运行(我还登录到进度“可见”的文件)。

当任务(从 repo 获取多个文件)完成时,对话框不会被应用程序破坏而是隐藏。稍后当一个新任务启动时,对话框再次显示,新启动任务的状态消息被打印并再次滚动,就像什么都没发生一样。

我试图在对话框回调函数中捕捉 WM_MOVE 和 WM_MOVING,将状态框设置为活动窗口(见代码)。到目前为止没有任何帮助。

当用户移动对话框时,我该怎么做才能使对话框不冻结? 有什么提示吗?

(顺便说一句,在调试的时候,我不能移动对话框,而且对话框中的列表框一直在更新,并且父级也被重绘了)

这里有一些代码(文件处理循环):

    pool = svnApiSvnIface.fp_svn_pool_create_ex(masterPool, NULL);
for(i=0; i<nFiles; i++)
{
    WaspLoggerLogPrintf(0, "%s - Processing: '%s' \n",
                        __FUNCTION__,
                        StripFilename(lpFileNames[i]));
    UpdateWindow(hwndParent);
    SetActiveWindow (hwndStatusBox);

    PrintMesgStatusBox("CheckFileStatus: for %s", StripFilename(lpFileNames[i]));
    revison.kind = svn_opt_revision_unspecified;
             :

这里是来自PrintMesgStatusBox() 函数的一些代码:

    if(UseStatusBox())
{
    int lbIndex = 0;
    int length = vsprintf(statusMessage, format, args);
    int printedLength = 0;
    while((printedLength + STATUSBOX_LINE_LENGTH) < length)
    {
        char tempChar = statusMessage[printedLength + STATUSBOX_LINE_LENGTH];
        statusMessage[printedLength + STATUSBOX_LINE_LENGTH] = '\0';
        SendDlgItemMessage(hwndStatusBox, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)&statusMessage[printedLength]);
        statusMessage[printedLength + STATUSBOX_LINE_LENGTH] = tempChar;
        printedLength += STATUSBOX_LINE_LENGTH;
    }
    SendDlgItemMessage(hwndStatusBox, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)&statusMessage[printedLength]);

    //AUTOSCROLL
    lbIndex = SendDlgItemMessage(hwndStatusBox, IDC_LIST1, LB_GETCOUNT, 0, 0) - 1;
    //Scroll to the newest item (put lbIndex to the top of the lb)
    SendDlgItemMessage(hwndStatusBox, IDC_LIST1, LB_SETTOPINDEX, lbIndex, 0);

    //redraw
    UpdateWindow(hwndStatusBox);
            :

【问题讨论】:

  • int printLength = 0; char tempChar = statusMessage[printedLength... 这是一些新的 C++11 魔法吗?
  • 我不确定我明白你的意思。您不喜欢在代码块 { some code } 的每个开头都初始化变量吗?没有魔法,只是 C。
  • 你说得对,我看错了你的代码。
  • 您正在与拥有该窗口的同一线程中运行一个长时间运行的任务。不要那样做!

标签: winapi dialog


【解决方案1】:

问题是由于我的代码循环和与 SVN 服务器长时间通信,消息队列似乎不再被处理。 由于我无法控制 IDE 的实现,我必须在我的 dll 中进行。

在循环中,我实现了一个函数,该函数消耗和分派对话框的消息(分别是所有消息)。

如果使用全部或仅使用对话框消息,结果会有所不同:

仅使用对话框消息:对话框会在每次 SVN 通信后更新,这会导致对用户操作的 UI 响应相当不稳定。但是 IDE 菜单保持可访问,这是想要的。

消费所有消息:UI对用户的响应比较流畅。但是可以访问 IDE 菜单,并且可以关闭 IDE 或启动其他操作。这是不需要的。

因此我只使用对话框消息。

一些代码(函数处理消息):

 void ProcessMessages(HWND hWnd, BOOLEAN peekHwndMsgsOnly)
 {
     MSG msg;
 HWND peekHwnd = NULL;

 if(peekHwndMsgsOnly)
 {
    peekHwnd = hWnd;
 }

     while(PeekMessage(&msg, peekHwnd, 0, 0, PM_REMOVE))
    {
        if(!IsDialogMessage(hWnd, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

原来阻塞消息处理的循环:

for(i=0; i<nFiles; i++)
{
    /*
    WaspLoggerLogPrintf(0, "%s - Processing: '%s' \n",
                        __FUNCTION__,
                        StripFilename(lpFileNames[i]));
    */

    PrintMesgStatusBox("CheckFileStatus: for %s", StripFilename(lpFileNames[i]));
    revison.kind = svn_opt_revision_unspecified;
    youngest = SVN_INVALID_REVNUM;
    internalfileName = svnApiSvnIface.fp_svn_dirent_internal_style(lpFileNames[i], pool);
    if (updateFromRepo) { PrintMesgStatusBox("    Retrieving repo status..."); }
    UpdateWindow(hwndParent);
    ProcessMessages(hwndStatusBox, TRUE);

    rtn = svnApiSvnIface.fp_svn_client_status4( &youngest,                              // svn_revnum_t *result_rev,
                                            internalfileName,                           // const char *path, 
                                            &revison,                                   // const svn_opt_revision_t *revision, 

这可能不是一个非常优雅的解决方案,但可以达到目的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 2022-11-24
    相关资源
    最近更新 更多