简体   繁体   中英

Circular button using BM_SETIMAGE and SetWindowRgn

I'm attempting to create a circular push button. Here's my process so far:

Create BS_BITMAP style button:

hButton = CreateWindow(L"button",L"Label",WS_CHILD|WS_VISIBLE|BS_BITMAP,
               122,363,65,65,hWnd,(HMENU)BUTTON_ID,NULL,NULL);

Load bitmap with LoadImage. The bitmap is a square, but I only want to display the circle in the center (more on this later):

buttonImage = (HBITMAP)LoadImage(hInstance,L"button.bmp",IMAGE_BITMAP,65,65, 
               LR_LOADFROMFILE|LR_CREATEDIBSECTION);

Set the button's image:

SendMessage(hButton,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)buttonImage);

In order to display just the circle, I use the following:

hButtonRgn = CreateEllipticRgn(0,0,65,65);
SetWindowRgn(hButton,hButtonRgn,TRUE);

Note that I define hButtonRgn globally and don't use it again, as the MSDN documentation for SetWindowRgn states that "the system owns the region specified by the region handle hRgn".

Here's the problem:

The button initially appears as only a circle. On being clicked and held, though, the full square bitmap appears, with white space surrounding the circle. However, upon release, only the circle appears again.

Here's my attempted solution:

As soon as the button is clicked, repaint the main window around the button. Within the main window's WndProc, then, I do the following:

case WM_PARENTNOTIFY:
    if ((int)wParam == WM_LBUTTONDOWN)
    {
        PAINTSTRUCT ps;
        BeginPaint(hWnd, &ps);
        pRenderTarget->BeginDraw();
        // paint the background surrounding the button in another function
        pRenderTarget->EndDraw();
        EndPaint(hWnd, &ps);
    }

However, this has no discernible effect. The button appears circular after releasing the mouse, but appears as a square when the mouse is being held down.

Any ideas on where I've gone wrong?

Your redraw routine is incorrect. BeginPaint() should only be used in response to a WM_PAINT message - it tells you that something is dirty and needs repainting. What you want to do is trigger that mechanism, and the way you do that is to use InvalidateRect() to mark the appropriate area of the parent window for redraw.

Even if this does improve things for you I think you'll end up with flickering which will probably be unacceptable. Another mechanism you could investigate is making the button owner draw, because then you can just draw it as a circle (and invalidate the parent window) in the same step.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM