minigui 1.6.8 thread版
OS: linux 2.6.20
CPU: s3c2410
最近在使用SetDlgItemText设置静态框文本时发现,在调用完这个函数后静态框的文本并没有立即显示出来,而是要等一会才能显示。我程序中的代码如下:
case MSG_TIMER:
SetDlgItemText (hWnd, ID_SYS_TIME, buffer);
McuGetStatus(&McuState);
return;
而当我把这两个函数调用换个位置时,静态框中的文本就能立即显示出来:
case MSG_TIMER:
McuGetStatus(&McuState);
SetDlgItemText (hWnd, ID_SYS_TIME, buffer);
return;
这时我以为是我的函数调用McuGetStatus(&McuState)出了某种错误,对SetDlgItemText (hWnd, ID_SYS_TIME, buffer)的调用有了某种影响,后来把这个函数换掉:
case MSG_TIMER:
SetDlgItemText (hWnd, ID_SYS_TIME, buffer);
sleep(3);
return;
依然是显示不出来,于是认为我原来的那个函数应该是起到了一种延时的作用。于是探索了一下SetDlgItemText的内部实现。
src/gui/Dialog.c line730-739
BOOL GUIAPI SetDlgItemText (HWND hDlg, int nIDDlgItem, const char* lpString) { HWND hCtrl; if ( !(hCtrl = GetDlgItem (hDlg, nIDDlgItem))) return FALSE; return SendMessage (hCtrl, MSG_SETTEXT, 0, (LPARAM)lpString) == 0; }
这里首先会根据主窗口的窗口句柄和静态框的ID找到
静态框的控件句柄。然后向静态框发送一个MSG_SETTEXT消息。
src/control/static.c line282-286
case MSG_SETTEXT: SetWindowCaption (hwnd, (char*)lParam); InvalidateRect (hwnd, NULL, TRUE); break;
在处理这个消息时,调用了InvalidateRect这个函数,
src/gui/window.c line4343-4379
BOOL GUIAPI InvalidateRect (HWND hWnd, const RECT* prc, BOOL bEraseBkgnd) { BOOL retval; PCONTROL pCtrl = (PCONTROL) hWnd; RECT rcInvalidParent; PMAINWIN pWin; MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE); pWin = MG_GET_WINDOW_PTR (hWnd); if (pCtrl && pCtrl->WinType == TYPE_CONTROL && pCtrl->dwExStyle & WS_EX_TRANSPARENT) { RECT rcInParent; rcInParent.left = pCtrl->cl; rcInParent.top = pCtrl->ct; rcInParent.right = pCtrl->cr; rcInParent.bottom = pCtrl->cb; if (prc) { RECT rcInvalid = *prc; OffsetRect (&rcInvalid, pCtrl->cl, pCtrl->ct); if (!IntersectRect (&rcInvalidParent, &rcInParent, &rcInvalid)) return FALSE; } else { rcInvalidParent = rcInParent; } hWnd = (HWND) pCtrl->pParent; prc = &rcInvalidParent; bEraseBkgnd = TRUE; } retval = wndInvalidateRect (hWnd, prc, bEraseBkgnd); PostMessage (hWnd, MSG_PAINT, 0, 0); return retval; }
在这个函数的倒数第三行首先调用wndInvalidateRect (hWnd, prc, bEraseBkgnd)将静态框中的文本擦除,然后调用PostMessage (hWnd, MSG_PAINT, 0, 0)向消息队列中邮寄一个消息。
由此可以知道上面的原因了。原来在调用完SetDlgItemText (hWnd, ID_SYS_TIME, buffer)函数之后,静态框中原来的文本被擦除,而新的文本并没有写到静态框中,只是向消息队列中发送了一个MSG_PAINT消息,要等到下一次消息循环处理MSG_PAINT时才能将文本写到静态框,而在SetDlgItemText (hWnd, ID_SYS_TIME, buffer)之后调用McuGetStatus(&McuState)就相当于延时,延迟了下一次消息循环的时间,所以会看不到文本。