Overcome Window Flicker While Dragging

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

While I use the CImageList control for dragging, I found it flickers in the owner window while draging and redraw the client region. I tried Google to find a solution, but there were no result, so I try to solve it myself.

Here’s my solution, which I’m very glad share with you!

First, you should register a new window class and create a new top most tool window, and move it’s position far off screen(I take 99000), so it’s not visible. The code would look like this:


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;
}

Second, move the window to properly position and paint it’s client. The code would look like this:

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;
}

Third, changes the position and dimensions for dragging support window by calling MoveWindow

Forth, move dragging to support the window’s postion far to screen. The code would look like this:

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:

First, in the InitInstance method of CWinApp’s subclass add code like this:

   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();

Then in dragging the owner window’s OnMouseMove, OnLButtonUp method calls DragBegin, DragMove, and DragEnd method of CImageDragWrapper, It’s very simple.


Note: you can compare CImageDragWrapper with CImageList by using my sample code!

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read