win32- 使用WM_NCPAINT在非客户区域绘制边框

摘要:
#pragmacomment(lib,“UxTheme”)#include#include LRESULTCALLBACKWndProc(HWND、UINT、WPARAM、LPAR);intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEChPrevInstance,LPSTRlpCmdLine,intnCmdShow
#pragma comment(lib, "UxTheme")
#include <windows.h>
#include <uxtheme.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = NULL;
    wcex.hCursor = (HICON)LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = CreateSolidBrush(RGB(0, 128, 0));
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"window";
    wcex.hIconSm = NULL;

    RegisterClassEx(&wcex);

    HWND hWnd = CreateWindowEx(
        NULL,
        L"window",
        NULL,
        WS_OVERLAPPEDWINDOW,
        100,
        100,
        600,
        400,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hWnd, nCmdShow);

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

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg) {
    case WM_CREATE:
        SetWindowTheme(hWnd, L"", L"");
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_NCCALCSIZE:
    {
        LPNCCALCSIZE_PARAMS ncParams = (LPNCCALCSIZE_PARAMS)lParam;
        ncParams->rgrc[0].top += 4;
        ncParams->rgrc[0].left += 4;
        ncParams->rgrc[0].bottom -= 4;
        ncParams->rgrc[0].right -= 4;
        return 0;
    }
    case WM_NCPAINT:
    {
        RECT rect;
        GetWindowRect(hWnd, &rect);
        HRGN region = NULL;
        if (wParam == NULLREGION) {
            region = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
        }
        else {
            HRGN copy = CreateRectRgn(0, 0, 0, 0);
            if (CombineRgn(copy, (HRGN)wParam, NULL, RGN_COPY)) {
                region = copy;
            }
            else {
                DeleteObject(copy);
            }
        }
        HDC dc = GetDCEx(hWnd, region, DCX_WINDOW | DCX_CACHE | DCX_INTERSECTRGN | DCX_LOCKWINDOWUPDATE);
        if (!dc && region) {
            DeleteObject(region);
        }
        HPEN pen = CreatePen(PS_INSIDEFRAME, 4, RGB(255, 0, 0));
        HGDIOBJ old = SelectObject(dc, pen);
        int width = rect.right - rect.left;
        int height = rect.bottom - rect.top;
        Rectangle(dc, 0, 0, width, height);
        SelectObject(dc, old);
        ReleaseDC(hWnd, dc);
        DeleteObject(pen);
        return 0;
    }
    case WM_NCACTIVATE:
        RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW);
        return 0;
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

 或者将WM_NCPAINT内的内容替换成下面的代码,效果一样

#ifndef DCX_USESTYLE
#define DCX_USESTYLE 0x00010000
#endif

case WM_NCPAINT:
    {
        HDC hdc = ::GetDCEx(hWnd, 0, DCX_WINDOW | DCX_USESTYLE);
        if (hdc) {
            RECT rcclient;
            ::GetClientRect(hWnd, &rcclient);
            RECT rcwin;
            ::GetWindowRect(hWnd, &rcwin);
            POINT ptupleft;
            ptupleft.x = rcwin.left;
            ptupleft.y = rcwin.top;
            ::MapWindowPoints(0, hWnd, (LPPOINT)&rcwin, (sizeof(RECT) / sizeof(POINT)));
            ::OffsetRect(&rcclient, -rcwin.left, -rcwin.top);
            ::OffsetRect(&rcwin, -rcwin.left, -rcwin.top);

            HRGN rgntemp = NULL;
            if (wParam == NULLREGION || wParam == ERROR) {
                ::ExcludeClipRect(hdc, rcclient.left, rcclient.top, rcclient.right, rcclient.bottom);
            }
            else {
                rgntemp = ::CreateRectRgn(rcclient.left + ptupleft.x, rcclient.top + ptupleft.y, rcclient.right + ptupleft.x, rcclient.bottom + ptupleft.y);
                if (::CombineRgn(rgntemp, (HRGN)wParam, rgntemp, RGN_DIFF) == NULLREGION) {
                    // nothing to paint
                }
                ::OffsetRgn(rgntemp, -ptupleft.x, -ptupleft.y);
                ::ExtSelectClipRgn(hdc, rgntemp, RGN_AND);
            }

            HBRUSH hbrush = ::CreateSolidBrush(RGB(255, 0, 0));
            ::FillRect(hdc, &rcwin, hbrush);
            ::DeleteObject(hbrush);

            ::ReleaseDC(hWnd, hdc);
            if (rgntemp != 0) {
                ::DeleteObject(rgntemp);
            }
        }
        return 0;
    }

免责声明:文章转载自《win32- 使用WM_NCPAINT在非客户区域绘制边框》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MySQL query_cache_type 详解第二节,surf特征检测关键点,实现图片拼接下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

如何利用JS检查元素是否在视口内

前言 分享两个监测元素是否在视口内的方法 1. 位置计算 使用 Element.getBoundingClientRect() 方法返回元素相对于视口的位置 const isElementVisible = (el) => {const rect = el.getBoundingClientRect();}; 获取浏览器窗口的宽高 const isE...

SVG DOM常用属性和方法介绍

将以Adobe SVG Viewer提供的属性和方法为准,因为不同解析器对JavaScript以及相关的属性和方法支持的程度不同,有些方法和属性是某个解析器所特有的。SVG支持DOM2标准。 12.2.1 文档初始化相关evt属性evt表示事件本身,可以通过evt获取与当前事件相关的信息,用户可以在script中定义响应函数,进行相应的处理。它与普通Jav...

Android检测View的可见性

Android中我们经常会用到判断View的可见行,当然有人会说View.VISIBLE就可以了,但是有时候这个真是满足不了,有时候我们为了优化,在View滚到得不可见的时候或者由于滚到只显示了部分内容的时候不做某些操作,View.VISIBLE这个时候是满足不了的。 1. onWindowVisibilityChanged检测滚到导致View可见或者不...

VR电脑模拟实现

一、概述 1.实现的基本操作是: 1)用手柄抓住黄色的方块代表手抓住鼠标。 2)通过移动手柄模拟鼠标移动,电脑屏幕上的光标跟着移动。 3)当光标移动到一个Button上时,Button高亮,离开时Button取消高亮,点击Button触发点击事件。 4)当点击Button之后,打开一个画图程序,可以用光标在颜色选择区选择一种颜色,然后在画图区根据光标的...

Android打开相机进行人脸识别,使用虹软人脸识别引擎

上一张效果图,渣画质,能看就好 功能说明: 人脸识别使用的是虹软的FreeSDK,包含人脸追踪,人脸检测,人脸识别,年龄、性别检测功能,其中本demo只使用了FT和FR(人脸追踪和人脸识别),封装了开启相机和人脸追踪、识别功能在FaceCameraHelper中。 实现逻辑: 打开相机,监听预览数据回调进行人脸追踪,且为每个检测到的人脸都分配一个tr...

使用 AFNetworking 进行 XML 和 JSON 数据请求

(1)XML 数据请求 使用 AFNetworking 中的 AFHTTPRequestOperation 和 AFXMLParserResponseSerializer,另外结合第三方框架 XMLDictionary 进行数据转换 使用 XMLDictionary 的好处:有效避免自行实现 NSXMLParserDelegate 委托代理协议方法来进行繁...