如何使用win32创建自定义框架

时间:2017-02-24 18:03:47

标签: c visual-studio winapi win32gui

我想创建一个容器控件,它有一个可选的边框,可以通过编程方式设置颜色和粗细。我还需要圆角,它必须只在C ++ win32中完成 - 没有MFC,ATL,winforms等。控件的目的只是包含其他控件。

我已经做了大量的阅读和实验,但是没有找到任何能够准确展示我尝试做什么的教程。以下代码最接近但失败,因为按钮侵占边框而不是被剪裁。如何剪辑儿童控件,使他们不要在边框上画画?

以下是在VS2015上运行的完整极简主义版本

#include "stdafx.h"
#include "Resource.h"
#include <windowsx.h>
#include <commctrl.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProcPanel(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

int APIENTRY wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInst, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
    WNDCLASSEX wc = {};

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInst;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = _T("main");
    RegisterClassEx(&wc);

    // Create main window.
    HWND MWhwnd = CreateWindowEx(NULL, _T("main"), _T(""), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);

    wc.lpfnWndProc = WndProcPanel;
    wc.hbrBackground = NULL;
    wc.lpszClassName = _T("CPanel");
    RegisterClassEx(&wc);

    // Create container panel
    HWND Panelhwnd = CreateWindowEx(NULL, _T("CPanel"), _T(""), WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 100, 20, 110, 100, MWhwnd, NULL, hInst, NULL);

    // Add Button to container panel
    CreateWindowEx(NULL, WC_BUTTON, _T("OK"), WS_VISIBLE | WS_CHILD, 0, 0, 50, 24, Panelhwnd, NULL, hInst, NULL);

    ShowWindow(MWhwnd, nCmdShow);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

/*--------------------------------------------------------------------------------------------------------------*/

LRESULT CALLBACK WndProcPanel(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_NCPAINT:  // here I'm creating the border
            {
                RECT rect;
                GetWindowRect(hwnd, &rect);
                OffsetRect(&rect, -rect.left, -rect.top);
                HDC hdc = GetWindowDC(hwnd);

                HRGN g_hrgnButton = CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 40, 40);
                FrameRgn(hdc, g_hrgnButton, CreateSolidBrush(RGB(50, 50, 255)), 5, 5);

                ReleaseDC(hwnd, hdc);
                return 0;
            }
        case WM_NCCALCSIZE:  // here I think I'm setting the client area size.
            {
                RECT *rc = (RECT*)lParam;
                InflateRect(rc, -5, -5);
                return 0;
            }
            break;
        case WM_PAINT:  // Setting the client area background color
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hwnd, &ps);

                RECT rect = ps.rcPaint;
                HRGN hrgn = CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 40, 40);
                SelectObject(hdc, GetStockObject(DC_BRUSH));
                SetDCBrushColor(hdc, RGB(0, 255, 0));
                PaintRgn(hdc, hrgn);

                EndPaint(hwnd, &ps);
            }
        }    
     return DefWindowProc(hwnd, msg, wParam, lParam);
}    

结果是:

enter image description here

如您所见,左上角边框被按钮覆盖。

0 个答案:

没有答案