系统管理Visual C++ 7.1Visual C++ 8.0Visual C++ 7.0Win32Windows 2000设计/图形Visual C++ 6.0Windows XPMFC中级开发WindowsC++
使用 CImageList克服拖动时的窗口闪烁
使用 CImageList克服拖动时的窗口闪烁
- 下载 ImageDragWrapper 源代码 - 2.97 KB
- 下载 TestDragDialog 演示程序 - 7.49 KB
- 下载 TestDragDialog 演示程序源代码 - 21.22 KB
引言
在使用 CImageList
控件拖动时,我发现其拥有窗口在拖动和重绘客户端区域时会闪烁。 我尝试在 Google 上查找解决方案,但没有找到任何结果,所以我自己尝试解决它。 这是我的解决方案,我非常乐意与大家分享!
背景
首先,注册一个新的窗口类并创建一个位于屏幕之外的、置顶的、工具窗口(我使用 99000),使其不可见。 代码如下:
BOOL CImageDragWrapper::Initialize()
{
if(m_hDragWnd)
{
return TRUE;
}
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
if(!::GetClassInfoEx(AfxGetInstanceHandle(), POPWINDOWCLASSNAM, &wcex))
{
wcex.style = CS_HREDRAW | CS_VREDRAW;
//specifies default window procedure
wcex.lpfnWndProc = (WNDPROC)DefWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = AfxGetInstanceHandle();
wcex.hIcon = LoadIcon(0, IDI_INFORMATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = 0;
wcex.lpszClassName = POPWINDOWCLASSNAM;
wcex.hIconSm = LoadIcon(0, IDI_INFORMATION);
RegisterClassEx(&wcex);
}
m_hDragWnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
POPWINDOWCLASSNAM,
_T(""),
WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS,
99000, 0, 6, 6,
0,
0,
AfxGetInstanceHandle(),
0
);
if(m_hDragWnd)
{
SetLayeredWindowAttributes(RGB(255,255,255), 100, /*0x00000001|*/0x0000002);
ShowWindow(m_hDragWnd, SW_SHOW);
UpdateWindow(m_hDragWnd);
}
return m_hDragWnd != 0;
}
其次,将窗口移动到正确的位置并绘制其客户端代码,如下所示:
BOOL CImageDragWrapper::DragBegin(HWND hDragWndOwner,int cxWnd, int cyWnd,
int cxHotSpotOffset, int cyHotSpotOffset,
const POINT& ptCurrentMousePos, HBITMAP hBack, int cxBackOffset, int cyBackOffset)
{
if(m_hDragWnd)
{
m_hDragWndOwner = hDragWndOwner;
m_cxHotSpotOffset = cxHotSpotOffset;
m_cyHotSpotOffset = cyHotSpotOffset;
POINT ptDest = ptCurrentMousePos;
ClientToScreen(m_hDragWndOwner, &ptDest);
::MoveWindow(m_hDragWnd,
ptDest.x - m_cxHotSpotOffset,
ptDest.y - m_cyHotSpotOffset,
cxWnd,
cyWnd, TRUE);
//Draw background image for dragging support window
if(hBack)
{ HDC hDC = ::GetDC(m_hDragWnd);
HDC hMemDC = ::CreateCompatibleDC(hDC);
HBITMAP hbmpOldMem = (HBITMAP)::SelectObject(hMemDC, hBack);
::BitBlt(hDC, 0,
0,
cxWnd,
cyWnd,
hMemDC,
cxBackOffset,
cyBackOffset,
SRCCOPY);
::SelectObject(hMemDC, hbmpOldMem);
::DeleteDC(hMemDC);
::ReleaseDC(m_hDragWnd, hDC);
}
}
return m_hDragWnd != 0;
}
第三,通过调用 MoveWindow
更改用于拖动支持窗口的位置和尺寸。
第四,将拖动支持窗口的位置移到屏幕之外。 代码如下:
BOOL CImageDragWrapper::DragEnd()
{
if(m_hDragWnd && m_hDragWndOwner)
{
m_hDragWndOwner = 0;
::MoveWindow(m_hDragWnd,
99000,
0,
6,
6, TRUE);
}
return m_hDragWnd != 0;
}
Using the Code
首先,在 CWinApp
的子类中,于 InitInstance
方法中添加如下代码:
CImageDragWrapper::Initialize();
CTestDragDialogDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{ // TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
CImageDragWrapper::Destroy();
然后在拖动拥有窗口的 OnMouseMove
和 OnLButtonUp
方法中调用 CImageDragWrapper
的 DragBegin
、DragMove
和 DragEnd
方法。 这很简单。 就这些了。
注意:你可以通过使用我的示例代码来比较 CImageDragWrapper
和 CImageList
!
关注点
这是我在国外网站上发布的的第一篇文章。 很抱歉我的英语水平有限,无法清楚地表达我的想法!
历史
- 2009/06/05 首次提交