-
Clipboard data in MDI
ok i have this procedure that will get a bitmap from the clipboard and display it in this child MDI window but the image will not show up until i move the window off the screen or if i resize it, does anyone see any flaws in this code. I am using Visual C++ 6 and Windows API on a windows XP box.
PHP Code:
LRESULT CALLBACK ClipProc( HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam )
{
HDC hdc;
HDC memhdc;
PAINTSTRUCT ps;
HWND hGetClip;
RECT rect;
BITMAP bm;
static HBITMAP hBitmap ;
HBITMAP hBitmapClip;
switch(Msg)
{
case WM_CREATE:
{
hGetClip = CreateWindowEx(0,"BUTTON","Get Image",WS_CHILD | WS_VISIBLE,
0,0,100,20,hWnd,(HMENU)HBUTTGETCLIP,NULL, 0);
break;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case HBUTTGETCLIP:
{
if (hBitmap)
{
DeleteObject (hBitmap) ;
hBitmap = NULL ;
}
OpenClipboard (copyhwnd);
hBitmapClip = (HBITMAP)GetClipboardData (CF_BITMAP) ;
if (hBitmapClip)
{
hBitmap = CopyBitmap (hBitmapClip) ;
}
CloseClipboard () ;
break;
}
default:
{
break;
}
}
break;
}
case WM_PAINT:
{
hdc = BeginPaint(hWnd,&ps);
if (hBitmap)
{
GetClientRect (hWnd, &rect) ;
memhdc = CreateCompatibleDC (hdc) ;
SelectObject (memhdc, hBitmap) ;
GetObject (hBitmap, sizeof (BITMAP), (PSTR) &bm);
SetStretchBltMode (hdc, COLORONCOLOR) ;
StretchBlt (hdc, 0, 0, rect.right, rect.bottom,
memhdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY) ;
DeleteDC (memhdc) ;
}
EndPaint(copyhwnd,&ps);
break;
}
default:
{
break;
}
}
return DefMDIChildProc(hWnd, Msg, wParam, lParam);
}
-
Windows will not post a WM_PAINT message until the window or a portion of it is invalidated. This happens when the window is restored, uncovered, resized or can be done explicitly with the InvalidateRect() function.
When you DeleteDC the device context must be in its original state. Note the following additions:
Code:
memhdc = CreateCompatibleDC (hdc) ;
/* Save old bitmap so it can be restored later. */
HBITMAP hOldBitmap = (HBITMAP) SelectObject (memhdc, hBitmap) ;
GetObject (hBitmap, sizeof (BITMAP), (PSTR) &bm);
SetStretchBltMode (hdc, COLORONCOLOR) ;
StretchBlt (hdc, 0, 0, rect.right, rect.bottom,
memhdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY) ;
/* Return DC to its original state before deleting. */
SelectObject(memhdc, hOldBitmap);
DeleteDC (memhdc) ;
-
I have tried this and it still has the same outcome. it will only show the clipboard data if i resize teh child window or if i move the window so that the body is not visible in the parent, like move it so you can only see the title bar that you are dragging it by and then bringing it back up.
-
Where is your call to InvalidateRect()? It should look something like:
Code:
case HBUTTGETCLIP:
{
if (hBitmap)
{
DeleteObject (hBitmap) ;
hBitmap = NULL ;
}
OpenClipboard (copyhwnd);
hBitmapClip = (HBITMAP)GetClipboardData (CF_BITMAP) ;
if (hBitmapClip)
{
hBitmap = CopyBitmap (hBitmapClip) ;
}
CloseClipboard () ;
/* Tell Windows to invalidate the entire client area and post a WM_PAINT message. */
InvalidateRect(hwnd, NULL, TRUE);
break;
}
-
ahh, ok. I was putting the wrong hwnd into the call. i had tried something before i posted and was using that hwnd instead. it works now, thanks.
-
Also
watch the uninitialised variables (ie hBitmap being tested for NULL)
and non static vars ie the edits hwnd will be lost.
The paints have a different hwnd used.
I recomend after
InvalidateRect(hwnd, NULL, TRUE);
you tell the app to bypass the OS msg que and draw your window immediately with UpdateWindow()