How to create a Win32 control to add other Win32 controls?

The Setup: years ago, we developed the excellent C ++ cross platform that managed many of the problems of writing source code between Mac OS X Windows. (we will not use the massive flaws of this approach - we developed this in 1993!).

To simplify the development of reusable components, we recently added the concept of a “panel” that contains several controls and user elements, mainly handling the hierarchical nature of drawing and other events, such as keystrokes and mouse clicks.

We have successfully developed this approach on the Mac OS X (Carbon) side. However, an attempt to move this approach to Windows (XP SP3 and beyond) has led to many messy problems: the continuous re-drawing of the contents of the window and events that are not transmitted to our “panels”.

On Windows, each panel is translated into a "window", and I suspect that this may be the root of the problem: overlapping elements "under" the closing element may interfere with the distribution of drawings and events.

Is there an accepted method for programmatically adding controls to a grouped hierarchy? Or are there certain FLAGS that must be installed to accomplish this?

(NOTE: although we are currently compatible with XP SP3, we do not need to - we could target our minimum OS on Windows 7. We are currently developing VS 2010)

Stephen

+5
source share
1 answer

A simple breakdown of how it usually works.

When you create a parent window (hereinafter referred to as the "panel") containing the children, the flicker is usually caused by the window procedure of the parent window that processes the WM_ERASEBKGND message and draws "from above" all its children before instructing the children to redraw themselves.

, , CS_CLIPCHILDREN, , DefWindowProc(), ( ). , " ", , .

Windows . .

: WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN ( ). Windows .

, , -, - ( ). WndProc() , , HWND.

. - .

RIGHT-CLICK , EDIT , ""!

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>

LRESULT __stdcall WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT __stdcall FrameProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT __stdcall SubClassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hpi, LPSTR lpcl, int ncs) {

    WNDCLASSEX wcex;
    MSG msg;
    HWND hWnd=0, hFrame=0, hEdit=0, hButton=0, hCheckBox=0;
    ATOM ca=0, caframe=0;
    RECT cr;
    HBRUSH framecolor;
int cx=0;
    char *ptr=(char *)&wcex;
    int i =0;
    for (;i<sizeof(wcex);i++) {
        ptr[i]=0;
    }
    wcex.cbSize=sizeof(wcex);
    wcex.hbrBackground = (HBRUSH) COLOR_WINDOW;
    wcex.hCursor = LoadCursor(0, IDC_ARROW);
    wcex.lpfnWndProc = &WndProc;
    wcex.lpszClassName = "mywnd";
    wcex.hInstance = hInstance;
    wcex.style = CS_HREDRAW|CS_VREDRAW;

    ca = RegisterClassEx(&wcex);

    for (i=0;i<sizeof(wcex);i++) {
        ptr[i]=0;
    }
    wcex.cbSize=sizeof(wcex);
    framecolor = CreateSolidBrush(0xFFA100);
    wcex.hbrBackground = (HBRUSH) framecolor;
    wcex.hCursor = LoadCursor(0, IDC_ARROW);
    wcex.lpfnWndProc = &FrameProc;
    wcex.lpszClassName = "myframe";
    wcex.hInstance = hInstance;
    wcex.style = CS_HREDRAW|CS_VREDRAW;
    caframe = RegisterClassEx(&wcex);


    hWnd = CreateWindowExA(0, (LPCSTR)ca, "My Window", WS_CLIPCHILDREN|WS_VISIBLE|WS_SYSMENU|WS_SIZEBOX, 100, 100, 500, 500, 0, 0, hInstance, 0);
    GetClientRect(hWnd, &cr);
    hFrame = CreateWindowExA(0, (LPCSTR)caframe, "", WS_VISIBLE|WS_BORDER|WS_CHILD|WS_CLIPCHILDREN, 10, 10, ((cr.right-cr.left)-20), ((cr.bottom-cr.top)-20), hWnd, (HMENU) 1, hInstance, 0);
    cx = ((cr.right-cr.left)-20)/2;
    hEdit = CreateWindowExA(0, "Edit", "Edit Control", WS_CHILD|WS_VISIBLE|WS_BORDER, 10, 10, cx, 20, hFrame, (HMENU) 2, hInstance, 0);
    hButton = CreateWindowExA(0, "Button", "Click Me!", WS_CHILD|WS_VISIBLE, cx+20, 10, 70, 20, hFrame, (HMENU) 3, hInstance, 0);

    /* Sub-Class the children */
    SetWindowLongPtr(hEdit, GWLP_USERDATA, GetWindowLongPtr(hEdit, GWLP_WNDPROC));
    SetWindowLongPtr(hButton, GWLP_USERDATA, GetWindowLongPtr(hButton, GWLP_WNDPROC));
    SetWindowLongPtr(hEdit, GWLP_WNDPROC, (LONG)&SubClassProc);
    SetWindowLongPtr(hButton, GWLP_WNDPROC, (LONG)&SubClassProc);

    if (!hWnd) {
        return -1;
    }
    while ( GetMessage(&msg, 0, 0, 0) ) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    DestroyWindow(hWnd);
    DeleteObject(framecolor);
    return 0;
}

LRESULT __stdcall WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    RECT rc;
    switch (uMsg) {
    case WM_WINDOWPOSCHANGING:
        GetClientRect(hWnd, &rc);
        SetWindowPos(GetDlgItem(hWnd, 1), 0, 0, 0, ((rc.right-rc.left)-20), ((rc.bottom-rc.top)-20), SWP_NOZORDER|SWP_NOMOVE);
        break;
    case WM_CLOSE:
        PostQuitMessage(0);
        break;
    default:
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}   

LRESULT __stdcall FrameProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    PAINTSTRUCT ps;
    WINDOWPOS *wp=0;
    POINT p;
    short wmid=0, wmevent=0;
    char message[300];
    switch (uMsg) {
    case WM_WINDOWPOSCHANGING:
        wp = (WINDOWPOS *)lParam;
        SetWindowPos(GetDlgItem(hWnd, 2), 0, 0, 0, (wp->cx/2), 20, SWP_NOMOVE|SWP_NOZORDER);
        SetWindowPos(GetDlgItem(hWnd, 3), 0, (wp->cx/2)+20, 10, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
        break;
    case WM_RBUTTONDOWN:
        p.x = (lParam & 0x0000ffff);
        p.y = (lParam >> 16 );
        sprintf(message, "The \"frame\" got a WM_RBUTTONDOWN message!\nx: %i\ny: %i\n",
            p.x, p.y);
        MessageBox(GetParent(hWnd), message, "Message", MB_ICONINFORMATION);
        break;
    case WM_COMMAND:
        wmid = (wParam & 0x0000ffff);
        wmevent = wParam>>16;
        switch (wmid) {
        case 3:
            if (wmevent==BN_CLICKED) {
                MessageBox(GetParent(hWnd), "You clicked my button!", "Notice", MB_OK);
            }
            break;
        default:
            break;
        }
        break;
    case WM_PAINT:
        break;
    default:
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

LRESULT __stdcall SubClassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    WNDPROC wp=0;
    POINT p;
    HWND hParent=0;
    char message[300];
    wp = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    if (!wp) {
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    if (uMsg==WM_RBUTTONDOWN) {
        p.x = (lParam & 0x0000ffff);
        p.y = (lParam >> 16 );
        sprintf(message, "Right-Click in control!\nx: %i\ny: %i\n\nNow, we'll convert this to the coordinates of the frame and pass the message up-stream!",
            p.x, p.y);
        hParent = GetParent(hWnd);
        MessageBox(GetParent(hParent), message, "Message", MB_ICONINFORMATION);
        ClientToScreen(hWnd, &p);
        ScreenToClient(hParent, &p);
        SendMessage(hParent, WM_RBUTTONDOWN, wParam, MAKELPARAM(p.x, p.y));
    }
    return CallWindowProc( wp, hWnd, uMsg, wParam, lParam);
}

Windows WM_COMMAND WM_NOTIFY. , . WM_COMMAND , A. B. C. (), EN_CHANGE.

, SendMessage() , .

, :

  • .
  • WM_PAINT.
  • , WM_PRINTCLIENT.
  • BitBlt()
  • , .

. bkausbk, . , , , BitBlt() WM_PAINT ( ), , .

PAINTSTRUCT ps;
case WM_PAINT:
    BeginPaint(hWnd, &ps);
    BitBlt(ps.hdc, 0, 0, cx, cy, hMemDC, 0, 0, SRCCOPY);
    EndPaint(hWnd &ps);

, , , , !

0

All Articles