-5

I am working on Zoom SDK which is based on win32 gui.

I have created 3 buttons using CreateWindow method on the window handle, which is provided by the ZoomSDK.

Code + Screenshot - 1

Now there are two problems with this.

  1. As soon as I click the buttons, they disappear.

See the Screen Shots BEFORE enter image description here

See the Screen Shots AFTER enter image description here

I want to know the reason why this is happening and how can I fix this?

        HWND hFirstView, hSecondView;


        cntrl->GetMeetingUIWnd(hFirstView, hSecondView);
        cntrl->MoveFloatVideoWnd(100, 100);

        HWND btnHwnd = CreateWindow(
            TEXT("button"),
            L"Open App",
            WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
            0, 0,
            50, 25,
            hFirstView,
            (HMENU)100,
            hInst,
            NULL);

        HWND btnHwnd2 = CreateWindow(
            TEXT("button"),
            L"Other",
            WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
            50, 0,
            50, 25,
            hFirstView,
            (HMENU)101,
            hInst,
            NULL);

        HWND btnHwnd3 = CreateWindow(
            TEXT("button"),
            L"Raise Hand",
            WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
            100, 0,
            50, 25,
            hFirstView,
            (HMENU)103,
            hInst,
            NULL);

        HDC hdc = GetDC(btnHwnd);
        SetBkColor(hdc, GetSysColor(COLOR_BTNSHADOW));
        SetTextColor(hdc, GetSysColor(COLOR_BACKGROUND));
        ReleaseDC(btnHwnd, hdc);
        int btnId = GetDlgCtrlID(btnHwnd);



        //oldWndProc = (WNDPROC) GetWindowLong(hFirstView, GWL_WNDPROC);
        oldWndProc = (WNDPROC) SetWindowLong(hFirstView,
            GWL_WNDPROC, (LONG)WndProc);

        SendMessage(btnHwnd, BM_SETSTATE, 1, 0);
        SetWindowText(hFirstView, L"Title");
  1. I want to handle click event for these buttons. I have tried to use SetWindowsLong to set another WndProc

        LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
        {
            int id = GetWindowLong(hWnd, GWL_ID);
    
            switch (message)
            {
            case WM_COMMAND: {
                MessageBox(NULL, L"Sign of releaf!", L"Whoaa!", 0);
                if (wParam == 1023) {
                    MessageBox(NULL, L"Sign of releaf!", L"Whoaa!", 0);
                }
            }
            break;
            }
            return CallWindowProc(oldWndProc, hWnd, message, wParam, lParam);
        }
    

Now, this WndProc gets called for other events such mouse move etc. It is not working for my three buttons. I want to handle click event i.e WM_COMMAND or any other technique possible.

Because I can not go inside the sdk (they don't provide sources, only .lib) so I can not change their WndProc, nor their internal WM_PAINT. The buttons are sort of overlay on top.

DivineCoder
  • 702
  • 5
  • 11
  • 2
    This site is for professionals. A window title named *"Fucking Title"* ain't so much professional. Besides, post code as **text**. Screenshots neither allow copying code, nor does it show up in text searches. – IInspectable Jul 29 '17 at 15:12
  • You should use something like Spy++ to inspect you buttons and figure out their positions and what messages they receive. – user7860670 Jul 29 '17 at 15:17
  • I have used breakpoints in Visual Studio - the switch statement for message variable, never enters the block for WM_COMMAND. Can Spy++ offer anything more than that? – DivineCoder Jul 29 '17 at 15:25
  • Spy++ allows inspection of widow properties and logging of their messages. – user7860670 Jul 29 '17 at 16:57

1 Answers1

0

You should not be calling SetBkColor() and SetTextColor() from outside a WM_PAINT handler. The correct way to color a button is to either:

  1. have the parent window handle the WM_CTLCOLORBTN notification.

    The WM_CTLCOLORBTN message is sent to the parent window of a button before drawing the button. The parent window can change the button's text and background colors. 

  2. give the button the BS_OWNERDRAW style, and then have the parent window handle the WM_DRAWITEM notification.

    Sent to the parent window of an owner-drawn button, combo box, list box, or menu when a visual aspect of the button, combo box, list box, or menu has changed.

Also, when a button sends a BN_CLICKED notification to its parent window, your subclass WndProc() doesn't need to use GetWindowLong(GWL_ID). First, you are calling it on the wrong HWND. And second, the button ID is carried in the message's wParam data.

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_COMMAND: {
            if (HIWORD(wParam) == BN_CLICKED) {
                switch (LOWORD(wParam)) {
                    case 100:
                    case 101:
                    case 103:
                        MessageBox(NULL, L"Sign of relief!", L"Whoaa!", 0);
                        break;
                }
            }
            break;
        }
    }
    return CallWindowProc(oldWndProc, hWnd, message, wParam, lParam);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Hey, thanks for the reply. If you see above, I am trying to subclass the main window i.e `hFirstView` which is the parent of Button. So WndProc should trap the WM_COMMAND, isn't it? – DivineCoder Jul 29 '17 at 16:31
  • The other issue which bothers me more is that the button disappears when I click on it or click anywhere on the parent window. Can that be the cause of the Click event not dispatched? – DivineCoder Jul 29 '17 at 16:33
  • The button completely disappears when I add | BS_OWNERDRAW to the style – DivineCoder Jul 29 '17 at 16:34
  • `case WM_PAINT: hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); return 0; case WM_CTLCOLORBTN: hdc = BeginPaint(hwnd, &ps); SetBkColor(hdc, GetSysColor(COLOR_BTNHIGHLIGHT)); SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT)); EndPaint(hwnd, &ps); RECT r; GetWindowRect(hwnd, &r); InvalidateRect(hwnd, &r, false); break;` I have added this to the WndProc too. Now the button flickers and disappears. – DivineCoder Jul 29 '17 at 17:15
  • WM_CTLCOLORBTN gets called, I have checked via the debugger. The button now flickers and disappear. Can this be because the parent WndProc is removing my objects (Painting on top them) from the window when calling WM_PAINT? – DivineCoder Jul 29 '17 at 17:17
  • @eureka: Did you even read the [documentation](https://msdn.microsoft.com/en-us/library/dd183362.aspx)? *"An application should not call BeginPaint except in response to a WM_PAINT message."* This looks like you don't really know what you're doing. Consider getting Petzold's [Programming Windows®, Fifth Edition](https://www.amazon.com/dp/157231995X). – IInspectable Jul 29 '17 at 18:49
  • @eureka: inside of `WM_PAINT`, the message's `hwnd` will be the parent window, not the button. [Read the documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/bb761849.aspx), `WM_CTLCOLORBTN` gives you the button's `HDC` in `wParam`, don't call `BeginPaint()` to get it, and the `lParam` is the button `HWND` – Remy Lebeau Jul 29 '17 at 20:32