文本字符输出澳门新葡萄京娱乐网站,转载几篇

作者:成人娱乐

问题:何以用易语言自绘gdi?

转发几篇外人写的皮肤类控件的技术小说

澳门新葡萄京娱乐网站 1

回答:

1 达成系统滚动条换肤作用

原连接:

上一篇大家浮现了什么应用Windows SDK创设基本控件,本篇来谈谈哪些输出文本字符。

以下二种自绘都可选择GDI或是GDI 完结1.控件自绘通过API 在子类化中收获WM_PAINT音信, BeginPaint()开端控件自绘,以EndPaint()结束其位图设备为各控件和窗口,所以通过此措施绘制的窗口存在控件句柄。优点:不须求手动描述控件音讯,只须要关爱控件的绘图缺点:窗口不可能兼而有之不一致折射率2.一心自绘窗口具备WS_EX_LAYERED属性,WM_PAINT新闻失效,只好通过API UpdateLayeredWindow进行窗口更新,全部控件均由自绘完毕,包涵自绘组件的音信也亟需手动完毕。优点:窗口可具有不一致发光度,那是控件自绘所达不到的弱项:全体控件均由自绘完结,包含自绘组件的音讯也亟需手动完毕。必要明白WINDOWS新闻机制,并拓宽自绘组件的音信模拟。窗口上的普通空间将不能展现,可是可经过得到WM_DRAWITEM 和WM_PAINT音信举办绘图,好处正是空中的具有事件都课使用,不要求自创模拟。

对此Windows系统中各样控件换肤功用,要数滚动条的换肤最难完成了,尤其是控件自带的连串滚动条,如Edit、ListBox、ListView、TreeView等自带的连串滚动条,要想实现其自定义的肌肤功用,用常规方法就像都无法儿落成。

 

在运用Win32编制程序时,大家常常要出口文本到窗口上,Windows全部的文本字符或许图片输出都是因此图片设备接口(GDI)进行的,Windows的三大骨干器件之一的GDI32.dll封装了具有的文件和图像输出。

对于健康的皮层定制平时都是经过定制WM_PAINT、WM_ERASEBKGND、WM_CTLCOLORxxx、NM_CUSTOMDRAW来兑现。但是系统滚动条的绘图,常规的、很阳光的法子行不通,微软把一条锦绣前程堵死了。依据自身的观赛测试,系统滚动条有为数不菲的新闻都对其奉行了绘图,这包涵WM_NCPAINT、WM_NCMOUSEMOVE、WM_NCMOUSELEAVE、WM_HSCROLL、WM_VSCROLL、WM_KEYDOWN、WM_MOUSEWHEEL等等,那些音讯中稍微可以定制,但多少无语定制。比方WM_HSCROLL就不能够定制,假使大家管理那么些音信,就不能够不团结调整滚动条的范围、地点、翻页值,而这个值大家日常不可能获取,微软一向未曾告诉大家,对于分裂的控件它操控滚动条到底选取何种政策,不精通。倘使大家不去定制这几个WM_HSCROLL,而暗中同意的管理它又进行滚动条的绘图,那不失为进退无路,叫人焦头烂额。当然不是完全未有主意,死路一条。为了克制障碍,翻越障碍,各类人有分化的安插,有攀岩翻越的,安全性不高;也是有走小路绕行的,相比费事。

贯彻控件的透明背景

  • GDI基本知识

在英特网再三查找,自个儿也留意切磋,基本有二种情势来促成系统滚动条换肤,一种格局是HOOK API,相当于拦截API的方法,还应该有一种是模拟法。

有的是情景下,大家需求控件 的背景是晶莹剔透的,正是供给直接观看控件父窗口的背景颜色、背景位图,譬如标签控件、单选Radio控件、复选Check控件,平时都须求在父窗口的背景上 实行绘图。但是必要控件的画布透明,那一个才具在GDI的文书档案中向来不见到Microsoft作任何表达,当然依旧有别的办法。

Windows下要绘制和出口文本,都以因此GDI(Graphics Device Interface,图形设备接口)实现的,GDI是windows在绘制图文时的设施上下文遇到,包涵画笔、画刷、字体、位图等三种与绘图有关的指标。设备条件(DC)在绘制中起重大的效应。差没有多少具有的绘图(包涵图形和文件)都与器械条件有关,注意“情形”的含义,就跟我们在画布上作画和写字一样,绘制时的画布是哪个,用的哪些笔,什么颜色,填充整个画布时用的什么样刷子等等,那便是大家的绘图时的情状,而Windows绘图的DC设备上下文就是平等的道理。设备条件句柄(HDC)正是用来描述DC的句柄,能够说,只要有了那个句柄,就有所了在窗口上输出图形和文件的基准。你收获了窗口顾客区的HDC,就足以在窗口顾客区上画;你拿走了窗口的非顾客区HDC,就能够在它上面画;你获得了桌面HDC,就能够直接在桌面上画……

拦截API,实际上是修改操作系统的API入口。因为系统绘制滚动条是透过种种绘制函数来促成的,举例SetScrollInfo(),基本种类经过这一类函数完成滚动条的绘图,对那一个API进行阻挠,约等于大家和睦写二个SetScrollInfo(),来亲自得以实现滚动条的绘图,以便由此完成滚动条的自定义绘制,完成大家想要的各个风格的皮肤外观。API的拦截有三种:一种是修改系统所装入内部存款和储蓄器可举行模块的导入地址,替换成我们所写的伪API的地点,使API调用能够自动跳转到那么些伪API上;还会有一种是直接修改API函数首地址处的多少机器指令,保存现场,写入跳转指令,使系统在进行到这么些API时能自动跳转到我们所写的伪API上。小编要说的是,那些拦截办法还真是有些邪门,有安全隐患,病毒就常干这种专门的学问。对操作系统举办那类暴力破解式的修改,很轻松招惹系统防火墙或反病毒软件报错,Windows原则上区别意干这种事;其二,一旦选择此法的次序因不胜而咽气,原来对操作系统的更动没有回复,那或者会危机到系统里的全数进度的牢固性,导致死机或运营分外。对于商业性的工程支出,往往很忧虑这点,都赞成于追求平稳,日常是宁用拙法,不玩巧技;其三,此法有线程同步难题:因为正值你改改程序指令相同的时候,若别的进度里的线程恰好推行到这里时候难点就能够发生出来,单CPU或然没啥难题,系统内存和CPU缓冲能够变成一同,但多核系统就难说了;其它这些点子还恐怕有移植性难题:在一种版本的系统中,通过拦截API有效,在另一种版本的种类中,就不见得还也是有效,究竟微软落到实处滚动条的绘图,它没明确一定就用哪些函数来落到实处,只怕新系统中它另有高招,API拦截也就不灵了。

 

获取器材条件句柄的方法有二种:一是管理WM_PAINT音信时,通过BeginPaint函数再次来到。别的一种就是经过GetDC、GetWindowDC的API函数获取。

上面作者要详细讲的是模拟法了,那几个格局不用拦截API,全数的技能实现都约束在系统所允许的范围内,咱谦虚严谨的当遵纪守法的好心人。

其一: 倘使程序帮衬桌面焦点服务来讲,则可调用大旨服务的API来促成背景。大家先看看这几个API:

  • 通过WM_PAINT音讯得到DC

所谓模拟法便是在系统滚动条的区域放置三个仿照窗口,这几个窗口特地用于绘制系统滚动条。当然大家也要拦截带滚动条控件的多少消息,以担保模拟窗口的绘图精确。上边只以ListView控件的水平滚动条为例,实行认证,垂直滚动条换肤能够列推。

HRESULT DrawThemeParentBackground(HWND hwnd , HDC hdc , RECT *prc );

Windows在检查实验到须要再一次绘制或许刷新窗口时,会积极须求管理WM_PAINT音信。举个例子在如下情形下就能够积极性求管理:

澳门新葡萄京娱乐网站 2

那个函数就是专程用来绘制父窗口的背景的,在那之中的hwnd参数是子窗口的句柄,hdc也时子窗口的画布句柄,prc是子窗口需绘制的区域,那么些函数实际是把父窗口的背景拷贝到子窗口上来,以这种艺术到达透明。

  1. 客户移动二个窗口,导致原来被盖住的部分窗口展现出来。
  2. 客户调解窗口的高低,并且窗口作风类型设置为CS_HREDRAW和CS_VREDRAW。
  3. 前后相继调用ScrollWindow恐怕ScrollDC函数滚动客商区。
  4. 先后调用InvalidateRect或许InvalidateTucsongn函数,该函数字展现示生产一条WM_PAINT消息。

率先大家要在滚动条的区域上创设一个效仿窗口,恰好覆盖滚动条:

 

咱俩得以在该音信中成就图文绘制,该音讯的拍卖具备特定的格式,必需在事实上绘制前调用BeginPaint,在绘制达成后调用EndPaint函数,也正是说大家须求把持有绘制的机能都放到那多个函数之间,并且HDC也不得不在那时期利用,不可能保存起来在别的地点采纳。使用WM_PAINT有叁个利润,就是windows会自身总括哪些区域必要革新,也等于说独有真正转移的地点才会更新,那样立异的代价会收缩到细微。

HWND hListView = ...;//ListView窗口的句柄

其二: 假如程序不支持桌面核心服务,则不可能选择方面包车型地铁主意,比方程序运维在Windows3000上。那时大家能够向父窗口发送WM_PAINT音讯,但是此音信所附带的wParam参数是二个画布句柄:

  • 经过API函数获取HDC

HWND pWnd = ::GetParent(hListView);

HDC dc = GetDC(NULL);

大家还足以经过GetDC、GetWindowDC函数来获得HDC,可是要在意,通过那个来赢得的HDC,能够保存起来在其他时候使用,不过要铭记一旦窗口有创新,必需想艺术另行绘制,不然就能够磨灭了。最终在利用完成后须求调用ReleaseDC来刑释,不然会产生能源败露。

HWND hBuddy = ::CreateWindowEx(WS_EX_NOACTIVATE, "Buddy_Window", "", WS_CLIPSIBLINGS|WS_DISABLED|WS_CHILD, 0, 0, 0, 0, pWnd, NULL, gModule, NULL);

HWND cWnd= ...;//子窗口句柄

  • 创建特定字体

Buddy_Window是您注册的一无所成反类犬窗口类。注意,窗口必须求有WS_DISABLED风格,那是个根本,那几个风格能够保险鼠标操作能够由此模拟窗口,而直白操控到所覆盖的滚动条,模拟窗口自己不接受别的鼠标键盘的输入。别的读取滚动条的矩形以及它的各种要素的可视、可用、压下等气象可由此GetScrollBarInfo()这几个API来实现,可是要证澳优些,这一个API有个别Bug,大家可去下载FreeCL 2.03版源码,里头改良了那个主题材料。

HWND pWnd= ...;//父窗口句柄

大家平时最广泛的文件输出是不须要本身成立字体的,因为周边的对象都有系统预约义好的。固然想出口点非常(非系统预约义的)字体,就必要大家创立并机关选入设备条件。成立字体首要有CreateFont和CreateFontIndirect,那多个函数的参数都游人如织,基本均等,具体用法看前边的实例。

成就创造模拟窗口之后,你要给ListView安装多个您写的窗口进度,以阻滞各样导致滚动条属性改变的种种新闻:

RECTcRect;

  • 兑现公文绘制

LRESULT CALLBACK MyListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

GetClientRect(cWnd,&cRect);

有了上边包车型大巴基础,我们就足以因此Windows的API来成功文本输出了,常用的文件输出函数有TextOut、DrawText、DrawTextExt、ExtTextOut等,那么些函数基本都有相似的参数,比方hdc,坐标地点,字符串。下边TextOut、DrawText、ExtTextOut为例来注明如何在Windows窗口中什么输出文本,别的请查看MSDN的用法。

{

HBITMAPbitmap = CreateCompatibleBitmap(dc, cRect.right,cRect.bottom);

#include <windows.h>
#include <tchar.h>

static TCHAR szAppName[] = TEXT("Textout");
static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
     HWND     hWnd;
     MSG      msg;
     WNDCLASS wndclass;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
     wndclass.lpfnWndProc   = WndProc;
     wndclass.cbClsExtra    = 0;
     wndclass.cbWndExtra    = 0;
     wndclass.hInstance     = hInstance;
     wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
     wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
     wndclass.lpszMenuName  = NULL;
     wndclass.lpszClassName = szAppName;

     if (!RegisterClass(&wndclass))
     {
          MessageBox (NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
          return 0;
     }

     hWnd = CreateWindow(szAppName,            // window class name
                          szAppName,           // window caption
                          WS_OVERLAPPEDWINDOW, // window style
                          CW_USEDEFAULT,       // initial x position
                          CW_USEDEFAULT,       // initial y position
                          400,                 // initial x size
                          300,                 // initial y size
                          NULL,                // parent window handle
                          NULL,                // window menu handle
                          hInstance,           // program instance handle
                          NULL);               // creation parameters

     ShowWindow(hWnd, iCmdShow);
     UpdateWindow(hWnd);

     while (GetMessage(&msg, NULL, 0, 0))
     {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
     }

     return msg.wParam;
}

static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hDC;
    PAINTSTRUCT ps;

    switch (message)
    {
    case WM_CREATE:
        return 0;
    case WM_PAINT:
        {
            RECT rect = {10, 30, 100, 50};
            TCHAR str[] = TEXT("English and 中文");

            hDC = BeginPaint(hWnd, &ps);
            TextOut(hDC, 10, 10, str, _tcslen(str));

            SetTextColor(hDC, RGB(255,0,0));
            DrawText(hDC, str, -1, &rect, DT_LEFT|DT_VCENTER);

            SetTextColor(hDC, RGB(0,255,0));
            INT dx[] = {8,8,8,8,16,8,8,8,16,8,8,8,10};
            ExtTextOut(hDC, 10, 50, 0, &rect, str, _tcslen(str), dx);

            SetTextColor(hDC, RGB(0,0,255));
            rect.right = 110;
            rect.top = 70;
            rect.bottom = 82;
            ExtTextOut(hDC, 10, rect.top, ETO_CLIPPED, &rect, str, _tcslen(str), dx);
            HFONT hFont = CreateFont(96,         // nHeight, 所创建字体的字符高度
                        0,           // nWidth,       字体的字符平均宽度
                        200,          // nEscapement,  字符输出方向与水平向右的方向所成角度,以0.1度为单位
                        0,             // nOrientation, 字符与基线的角度,以0.1度为单位
                        FW_BOLD,        // nWeight,      字符颜色的深浅度
                        TRUE,            // bItalic,      斜体属性标志(FALSE:正常字体,TRUE:斜体)
                        FALSE,            // bUnderline,   下划线属性标志(FALSE:无下划线,TRUE:有下划线)
                        FALSE,             // cStrikeOut,   删除线属性标志(FALSE:无删除线,TRUE:有删除线)
                        ANSI_CHARSET,       // nCharSet,        字符集标识0:ANSI字符集,1:系统缺省字符集
                        OUT_DEFAULT_PRECIS,  // nOutPrecision,   输出精度
                        CLIP_DEFAULT_PRECIS, // nClipPrecision,  剪切精度
                        DEFAULT_QUALITY,      // nQuality,        输出品质
                        DEFAULT_PITCH|FF_SWISS, // nPitchAndFamily, 字符间距
                        TEXT("Arial"));          // lpszFacename,    现有系统TrueType字体名称
            HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);
            SetBkMode(hDC, TRANSPARENT);
            SetTextColor(hDC, RGB(0x00, 0xFF, 0xFF));
            TextOut(hDC, 0, 150, TEXT("创建Font"), 6);
            DeleteObject(hFont);
            EndPaint(hWnd, &ps);
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0 ;
    }
    return DefWindowProc (hWnd, message, wParam, lParam);
}

case WM_LBUTTONDOWN:

ReleaseDC(dc);

 

    ......

HDCmemDC = CreateCompatibleDC(NULL);

程序运维,点击鼠标左键后效果如下:

case WM_LBUTTONDBLCLK:

HGDIOBJoldBitmap = SelectObject(memDC, bitmap);

澳门新葡萄京娱乐网站 3

    ......

//此处能够调用SetClipRect()等函数来限制绘制范围

前后相继中的DrawText、ExtTextOut能安装文本输出的矩形范围,超出部分是看不见的,从运维结果我们也得以看看有两行展现不全,正是出于设置的呈现范围小的原因。

case WM_NCMOUSEMOVE:

SendMessage(pWnd, WM_ERASEBKGND, (WPARAM)memDC,0); 

其他ExtTextOut函数仍是能够安装字符的距离,运营结果的第三行正是这种温馨设置间距不平等的结果。

    ......

SendMessage(pWnd, WM_PAINT, (WPARAM)memDC,0);

本程序还用CreateFont函数创设了二个斜体、右上排列的文本串。通过上例,大家把常用的文件输出作为实例体现给大家,只要好赏心悦目待实例代码,在组合MSDN的求证,再增多本体系的第一篇的Windows编制程序基本框架,一定能够通晓好Windows编制程序的主干文件输出。

case WM_NCMOUSELEAVE:

//至此memDC上曾经保存了父窗口的背景内容

 

    ...... 

//顾客能够调用BitBlt(...)等函数拷贝memDC的内容到子窗口的某部区域,那样就到达了晶莹剔透效果;

精细入微微信公众平台:工程师互动联盟(coder_online),你能够第临时间获取原创技能小说,和(java/C/C /Android/Windows/Linux)技艺大咖交欢人,在线交换编制程序经验,获取编制程序基础知识,解决编制程序难点。技师互动联盟,开拓职员本身的家。

}

SelectObject(memDC, oldBitmap);

澳门新葡萄京娱乐网站 4

......

DeleteDC(memDC); 

转发请阐明出处,多谢同盟!

gOldListViewProc = (WNNPROC)::GetWindowLong(hListView, GWL_WNDPROC);

DeleteObject(bitmap);

::SetWindowLong(hListView, GWL_WNDPROC, LONG(&MyListViewProc));//安装窗口过程

位置的点子当然有限定,因为不是兼具的父窗口都基本上能用这种奇特的WM_PAINT音信功用,但是MSDN中涉及大大多控件都有那些效能,咱们要留意读它的文档内容。

 

 

新闻管理

其三: 要是地点的议程都十一分的话,就剩下最笨的措施了,用GDI函数涂刷子窗口的背景,但您事先就要掌握父窗口的背景颜色、背景位图等音讯。例如拿父窗口的水彩来填充子窗口的背景,能够调用FillRect()等:

率先我们要阻拦WM_NCLBUTTONDOWN 和 WM_NCLBUTTONDBLCLK那么些音讯,当你在滚动条上按下鼠标时,就马上触发WM_NCLBUTTONDOWN,就算老是火速按两下鼠标就还可能有WM_NCLBUTTONDBLCLK。注意双击时唯有贰个WM_NCLBUTTONDOWN新闻,实际不是多个。第一遍按鼠标相会世贰个WM_NCLBUTTONDBLCLK。实际上那七个音讯我们完全能够等而视之,做一样的拍卖。系统在拍卖那个多个消息时,都会在其内处中触发许多别样音信,其中有好七个WM_HSCROLL、WM_CAPTURECHANGED、WM_NCMOUSELEAVE。大家入眼是要管理WM_HSCROLL,因为它最有价值。在您放手鼠标后,系统一发布送并管理完最终三个WM_HSCROLL之后,这才从WM_NCLBUTTONDOWN或WM_NCLBUTTONDBLCLK中返回:

//-------------------父窗口的背景是颜色的情事

if(msg == WM_NCLBUTTONDOWN || msg == WM_NCLBUTTONDBLCLK)

COLO奥德赛REFpColor = ...;//父窗口的颜色

{

HDC cDC =...;//子窗口的画布句柄

    //注意暗中同意管理会有N个WM_HSCROLL新闻出现,要等你的按下拖拽操作完毕后,那一个调用才回到

RECTcRect = ...;//子窗口需刷新的区域 

    //在那个调用内部,作者猜测系统会进去一种消息循环,因为按住左键之后,WM_NCMOUSEMOVE

HBRUSHbrush = CreateSolidBrush(pColor);

    //和WM_NCLBUTTONUP都不再触发了。其内部估算是捕捉了WM_NCMOUSEMOVE音信,因之一再刷新滚动

FillRect(cDC, &cRect,brush);

    //盒的职位,若有须要你可设置鼠标钩子,以捕捉鼠标移动音信,以即时刷新模拟窗口中滚动盒的

DeleteObject(brush);

    //的地方。若只是响应WM_HSCROLL音讯,你大概以为滚动盒的拖拽比较滞,不平易。

 

   

//-------------------父窗口的背景是位图的图景

    //SetWindowsHookEx(...);

HBITMAPpBitmap = ...;父窗口的背景位图

    LRESUTL code = ::CallWindowProc(gOldListViewProc, hListView, msg, wParam, lParam);

HDC cDC =...;//子窗口的画布句柄

    //UnhookWindowsHookEx(...);

RECTcRect = ...;//子窗口需刷新的区域 

   

POINTrp;

    return code;

SetBurshOrgEx(cDC, x, y,&rp);假设是位图刷子,则还要求调动画布的刷子原点偏移确认保证无缝

}

HBRUSHbrush = CreatePatternBrush(pBitmap);

 

FillRect(cDC, &cRect,brush);

作者建议我们去微软的网址下载ControlSpy 2.0其一小工具,它用来监视控件的消息,那东西很有用。

DeleteObject(brush);

下边大家再看WM_HSCROLL音信,这一个音信平日是系统管理WM_NCLBUTTONDOWN或者WM_NCLBUTTONDBLCLK时发生的,但有的时候候也说不定是前后相继特意发送的,和滚动条操作没有关联。

SetBurshOrgEx(cDC, rp.x, rp.y,NULL);还原画布的刷子偏移

if(msg == WM_HSCROLL)

 

 

    ::CallWindowProc(gOldListViewProc, hListView, msg, wParam, lParam);

揭示换肤本事:定制控件背景颜色与背景位图

 

正文汇报怎样定制控件的背景颜色和背景位图的手艺。

率先要说一下控件的绘图进度:当控件的有个别区域需求重绘时,都会触发WM_ERASEBKGND和WM_PAINT音信。譬如控件的某些区域被另三个主次的窗口挡住了,而后这个窗口又被移走了,那时间调控件被挡住的原委就供给再度绘制了。

先是步:系统向控件发送WM_ERASEBKGND音讯以促成背景的擦除职业(不经常不发送,比如顾客大概调用InvalidateRect(),其参数却钦赐不擦除背景,那样就未有那些音讯);

其次步:系统向控件的窗口进度发送WM_PAINT音信,控件实施拍卖这几个WM_PAINT音讯时会有选取地触发前边三个步骤的动作;

其三步:对于有些专门的职业控件,如Button、Edit、ListBox、 ScrollBar、Static控件,它还有恐怕会向父窗口发送WM_CTLCOLORxxx(WM_CTLCOLORBUTTON、 WM_CTLCOLOREDIT、WM_CTLCOLORSTATIC、WM_CTLCOLORLISTBOX、 WM_CTLCOLOCR-VSCROLLBA中华V等)的音信,那一个信息再次回到三个刷子句柄,系统拿这些刷子句柄进一步涂刷本身的背景。别的还发掘Trackbar 也会向父窗口发送WM_CTLCOLO汉兰达STATIC信息,TreeView在少数情形下也可以有,不过自身未曾看出微软在怎么地点对那一点作表明;作者一时发现很两人管理那个音信时,喜欢给系统再次回到三个NULL_BRUSH的空刷子,以为这么系统就不会把前面步骤画好的背景覆盖掉,其实不确定的,有个别控件不覆 盖,某些就不平日,像Trackbar正是如此,要当心。

第四步:对于菜单和无数规范控件,如Button、Edit、ListBox、 Static、ComboBox它只怕会向父窗口发送WM_MEASUREITEM和WM_DRAWITEM新闻,其它通用控件Tab、 StatusBar、ListView、Header也说不定会有WM_DRAWITEM音信;但对于相当多通用控件,如TreeView、 ListView、Rebar、Trackbar、Toolbar等,它会向父窗口发送大多其ID为NM_CUSTOMDRAW的WM_NOTIFY新闻。对于那二种音讯,实际须要顾客在已经涂刷好的背景之上再实践本人的绘图职业;

第五步:当控件的WM_DRAWITEM或者WM_NOTIFY新闻未有被客商管理时,系统会亲自实行自个儿的暗中认可绘制专门的学业,把控件画出来,这一步未有艺术重载。

知情了那么些步骤,差非常少大家心坎已经清楚,知道如何定制控件的背景颜色和背景位图了。常常境况下大家定制第一步、第三步达成本身的例外背景,定制第四部落成控件本身的超过常规规绘制。乃至大家得以全方位重载控件第一步的WM_ERASEBKGND消息和第 二步的WM_PAINT音讯,控件背景和控件绘制全部温馨解决,没人说这么做极度。然则要专一,当自身完毕WM_PAINT消息的重载管理时,后边3个步 骤就都不发出了。

定制颜色倒是很粗大略,依据控件的项目处理WM_ERASEBKGND、 WM_CTLCOLORxxx、WM_DRAWITEM、WM_NOTIFY音讯了,日常情状下,定制WM_ERASEBKGND和 WM_CTLCOLOENVISIONxxx就能够了;对于背景位图很多控件却专门费力,像List博克斯,你把背景位图涂刷好,结果因为顾客操作滚动条或鼠标滚轮或按 方向键,背景位图也时有发生滚动,这就只可以重绘位图,对于背景颜色就从不那些难题,不管怎么滚动,颜色照旧那贰个颜色,位图就不行,要求团结重载发生滚动操作 的种种信息以促成位图重绘。微软就像并不要是你会修改控件的背景位图,它从不对那一个意况作打算,总是不假思索的对控件画布实行Scroll操作。真正贯彻 背景位图的措施平时迫使大家要阻拦那二个导致窗口内容爆发滚动的各类操作,由此位图背景的意义落成也总令人认为有一些规范、不那么可靠。

最终要证实的是:假设父控件还蕴藏背景透明的子控件,你应有重载父控件的WM_ERASEBKGND音信,不然那多少个透明背景的子控件大概就未有科学的背景内容。

地点这几个步骤是本身个人的掌握,不肯定对哦!仅供参考。

 

    //1)读取滚动条的数码

爆料换肤本领:完成系统滚动条换肤功用

对于Windows系统中种种控件换肤作用,要数滚动条的换肤最难完结了,尤其是控件自带的系统滚动条,如Edit、ListBox、ListView、TreeView等自带的类别滚动条,要想完成其自定义的肌肤功能,用健康方法就像是都不能够兑现。

对于健康的皮层定制平常都是经过定制WM_PAINT、WM_ERASEBKGND、 WM_CTLCOLORxxx、NM_CUSTOMDRAW来达成。然则系统滚动条的绘图,常规的、很阳光的章程行不通,微软把一条锦绣前程堵死了。根据作者的观看比赛测量试验,系统滚动条有无数的信息都对其实践了绘图,那包罗WM_NCPAINT、WM_NCMOUSEMOVE、WM_NCMOUSELEAVE、 WM_HSCROLL、WM_VSCROLL、WM_KEYDOWN、WM_MOUSEWHEEL等等,那几个信息中稍加能够定制,但有些无语定制。比方WM_HSCROLL就不能够定制,假设大家处理这一个新闻,就必需和睦支配滚动条的限制、地点、翻页值,而这一个值我们日常无法得到,微软有史以来未有报告大家, 对于差异的控件它操控滚动条到底采取何种政策,不清楚。假如我们不去定制这一个WM_HSCROLL,而私下认可的拍卖它又实践滚动条的绘图,那就是进退无路, 叫人力不胜任。当然不是截然没办法,死路一条。为了克制阻碍,翻越障碍,每一个人有例外的国策,有攀岩翻越的,安全性不高;也可以有走小路绕行的,比较吃力。

在互连网一再查找,本人也精研,基本有二种艺术来贯彻系统滚动条换肤,一种艺术是HOOKAPI,也正是拦截API的格局,还也是有一种是模拟法。

拦截API,实际上是修改操作系统的API入口。因为系统绘制滚动条是通过种种绘制函数来达成的,比方SetScrollInfo(),基本体系经过这一类函数落成滚动条的绘图,对这一个API实行拦阻,也便是大家休戚相关写贰个SetScrollInfo(),来亲自落实滚动条的绘图,以便因而完结滚动条的自定义绘制,完结我们想要的各样风格的肌肤外观。API的阻止有三种:一 种是修改系统所装入内部存款和储蓄器可进行模块的导入地址,替换来大家所写的伪API的地点,使API调用能够自行跳转到这几个伪API上;还会有一种是直接修改API函 数首地址处的几何机器指令,保存现场,写入跳转指令,使系统在奉行到那么些API时能自动跳转到大家所写的伪API上。笔者要说的是,这么些拦截办法还真是有个别邪门,有安全祸患,病毒就常干这种职业。对操作系统进行那类暴力破解式的修改,很轻便招惹系统防火墙或反病毒软件报错,Windows原则上差别意干这种 事;其二,一旦选拔此法的顺序因不胜而咽气,原来对操作系统的修改未有回复,那也许会危机到系统里的富有进度的安宁,导致死机或运行十分。对于商业性的 工程开拓,往往很忧郁那或多或少,都帮忙于追求安定,经常是宁用拙法,不玩巧技;其三,此法有线程同步难题:因为正值你改改程序指令同不时间,若其余进度里的线程 恰好实施到此处时候难点就能够产生出来,单CPU或者没啥问题,系统内存和CPU缓冲可以成功同步,但多核系统就难说了;另外那么些艺术还也可以有移植性难点:在一 种版本的连串中,通过拦截API有效,在另一种版本的系统中,就不见得还大概有效,毕竟微软落到实处滚动条的绘图,它没规定一定就用哪个函数来促成,大概新体系中 它另有高招,API拦截也就不灵了。

下边作者要详细讲的是模拟法了,这些法子不用拦截API,全数的技术实现都约束在系统所允许的限制内,咱提心吊胆的当规行矩步的令人。

所谓模拟法正是在系统滚动条的区域放置一个模拟窗口,那一个窗口特意用来绘制系统滚动条。当然大家也要拦截带滚动条控件的若干音信,以管教模拟窗口的绘图正确。下边只以ListView控件的水准滚动条为例,实行求证,垂直滚动条换肤能够列推。

澳门新葡萄京娱乐网站 5

第一我们要在滚动条的区域上创造贰个仿照窗口,恰好覆盖滚动条:

HWND hListView =...;//ListView窗口的句柄

HWND pWnd = ::GetParent(hListView);

HWND hBuddy =::CreateWindowEx(WS_EX_NOACTIVATE, "Buddy_Window", "",WS_CLIPSIBLINGS|WS_DISABLED|WS_CHILD, 0, 0, 0, 0, pWnd, NULL,gModule, NULL);

Buddy_Window是您注册的效仿窗口类。注意,窗口一定要有WS_DISABLED 风格,那是个重大,这么些风格能够保险鼠标操作能够透过模拟窗口,而直白操控到所覆盖的滚动条,模拟窗口本身不接受其余鼠标键盘的输入。其他读取滚动条的矩 形以及它的相继要素的可视、可用、压下等状态可通过GetScrollBarInfo()那么些API来完结,但是要证实有些,那几个API某个Bug,大家可去下载FreeCL2.03 版源码,里头改进了这么些主题素材。

姣好创设模拟窗口之后,你要给ListView安装二个您写的窗口进程,以堵住各类导致滚动条属性更换的各种新闻:

LRESULT CALLBACK MyListViewProc(HWNDhwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

case WM_LBUTTONDOWN:

    ......

case WM_LBUTTONDBLCLK:

    ......

case WM_NCMOUSEMOVE:

    ......

case WM_NCMOUSELEAVE:

   ...... 

}

......

gOldListViewProc =(WNNPROC)::GetWindowLong(hListView, GWL_WNDPROC);

::SetWindowLong(hListView, GWL_WNDPROC,LONG(&MyListViewProc));//安装窗口进度

 

音信管理 :

先是大家要阻拦WM_NCLBUTTONDOWN 和WM_NCLBUTTONDBLCLK那四个新闻,当你在滚动条上按下鼠标时,就立时触发WM_NCLBUTTONDOWN,倘若总是急迅按两下鼠标就 还可能有WM_NCLBUTTONDBLCLK。注意双击时只有一个WM_NCLBUTTONDOWN音信,实际不是五个。第三遍按鼠标会出现一个WM_NCLBUTTONDBLCLK。实际上那四个音信我们一起能够等而视之,做同样的管理。系统在拍卖那个八个音讯时,都会在其内处中触发非常多别的音信,当中有若干个WM_HSCROLL、WM_CAPTURECHANGED、WM_NCMOUSELEAVE。大家珍视是要处理WM_HSCROLL,因为它最有价值。在您松开鼠标后,系统一发布送并管理完最终一个WM_HSCROLL之后,这才从WM_NCLBUTTONDOWN或 WM_NCLBUTTONDBLCLK中返回:

if(msg == WM_NCLBUTTONDOWN || msg== WM_NCLBUTTONDBLCLK)

{

   //注意暗中认可管理会有N个WM_HSCROLL音讯出现,要等您的按下拖拽操作完毕后,这几个调用才回去

   //在那一个调用内部,笔者推断系统会进去一种音信循环,因为按住左键之后,WM_NCMOUSEMOVE

    //和WM_NCLBUTTONUP都不再触发了。其里面估算是捕捉了WM_NCMOUSEMOVE新闻,因之屡次刷新滚动

   //盒的职位,若有供给你可安装鼠标钩子,以捕捉鼠标移动音讯,以那时刷新模拟窗口中滚动盒的

   //的职位。若只是响应WM_HSCROLL新闻,你可能以为滚动盒的拖拽相比较滞,不平坦。

 

   //SetWindowsHookEx(...);

    LRESUTL code= ::CallWindowProc(gOldListViewProc, hListView, msg, wParam,lParam);

    //UnhookWindowsHookEx(...);

 

    returncode;

}

 

自己提出大家去微软的网址下载ControlSpy2.0 以此小工具,它用来监视控件的音讯,那东西很有用。

上面大家再看WM_HSCROLL信息,那个音信日常是系统管理WM_NCLBUTTONDOWN或者WM_NCLBUTTONDBLCLK时发出的,但有的时候候也或许是前后相继特意发送的,和滚动条操作未有涉及。

if(msg == WM_HSCROLL)

   ::CallWindowProc(gOldListViewProc, hListView, msg, wParam,lParam);

   //1)读取滚动条的数量

   //2)再在模拟窗口上绘制滚动条

    //......

    return0;

}

别的还会有非常多此外的新闻大概引致滚动条属性的变型,如客户的键盘操作、鼠标滚轮操作大概导致 滚动条的Thumb地方暴发改动,那个操作分别产生WM_KEYDOWN和WM_MOUSEWHEEL,而系统又在那多个音信中试行滚动条的绘图,由此你 必得截获它们,但拍卖措施同WM_HSCROLL,这里不再啰嗦了。

当我们未有按下鼠标左键时,只是不难地在滚动条移动鼠标时,大家会意识滚动条的开关和 Thumb都会自动高亮,其实这个变化都以系统在WM_NCMOUSEMOVE和WM_NCMOUSELEAVE中绘制完结的。比方当鼠标步向到 Thumb上时,它就高亮了,当鼠标离开它,它又变葡萄紫了,你要分别管理WM_NCMOUSEMOVE和WM_NCMOUSELEAVE这五个音信。注意 唯有ListView应用主旨风格之后才恐怕有WM_NCMOUSELEAVE信息,古板风格的ListView就从不这几个消息,只有WM_NCMOUSEMOVE音信,由此管理高亮还真有一点麻烦。便是因为宗旨风格和价值观风格的反差,由此笔者提议你也管理WM_THEMECHANGED音信,以识别不一样的大旨方式,完成分化高亮管理。看下边那么些图,TreeView的滚动条是主旨风格的,但ListView的滚动条是观念风格的,但自己加了 换肤功用。

别的,大家还应该拦截处理ListView的WM_NCPAINT,将滚动条的区域抠掉,不让它绘制滚动条。就算滚动条被模仿窗口遮住了,但要么有至关重要这么做,以幸免出现意外情形:

if(msg == WM_NCPAINT)

{

    HRGN wRgn =NULL; 

    RECTsbRect = GetScrollBarRect();//读取滚动条矩形的四个函数

    HRGNsRgn = ::CreateRectRgn(sbRect.left, sbRect.top, sbRect.right,sbRect.bottom

    if(wParam ==1)

    {

       RECT wRect;

       ::GetWindowRect(hListView, &wRect);

       wRgn = ::CreateRectRgn(wRect.left, wRect.top, wRect.right,wRect.bottom););

       wRgn = ::CombineRgn(wRng, wRgn, sRgn, RGN_DIFF);

    }

    else

    {

        wRgn= (HRGN)wParam; 

       wRgn = ::CombineRgn(wRng, wRgn, sRgn, RGN_DIFF);

    }

    ::DeleteObject(sRgn);

   ::CallWindowProc(gOldListViewProc, hListView, WM_NCPAINT,WPARAM(wRgn), 0);

    if(wParam ==1)

       ::DeleteObject(wRgn);

    return0;

}

另外,还要拦截WM_WINDOWPOSCHANGING新闻,因为当ListView的位置、尺寸、Z秩序爆发改动时要立即调动模拟窗口的职位、尺寸、Z秩序。为啥要在WM_WINDOWPOSCHANGING中进行,而不选择在 WM_WINDOWPOSCHANGED或WM_MOVE或WM_SIZE中张开呢?因为在WM_WINDOWPOSCHANGING中拍卖,可让模拟窗 口先于ListView调节自个儿的职责、尺寸和Z,可制止有个别制图问题。实际小编在FreeCL中既用了WM_WINDOWPOSCHANGING,也用到 WM_WINDOWPOSCHANGED四个音讯。在管理WM_WINDOWPOSCHANGING时调度任务、尺寸、Z秩序,在拍卖 WM_WINDOWPOSCHANGED时,强制重绘模拟窗口。

末尾还要表明某个的是,系统可能因为客户改动控件尺寸导致其滚动条自动消失或自行展现,只怕调节滚动条的可用状态,如你拉宽辅助多行展现的Edit控件,会招致滚动条箭头按键变灰,Thumb消失。那么些动作日常都是在 WM_WINDOWPOSCHANGED中达成的,由此这么些新闻也亟需拦截管理:

if(msg == WM_WINDOWPOSCHANGED)

{

    LRESULTlReturn = ::CallWindowProc(gOldListViewProc, hListView,WM_WINDOWPOSCHANGED,

       wParam, lParam);

   if(::GetNextWindow(hBuddy, GW_HWNDNEXT ) !=hListView)

   {  //调解模拟窗口的Z-Order,确认保证其紧贴ListView之上

       HWND hAbove = ::GetNextWindow(hListView, GW_HWNDPREV);

       UINT flag =SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOSENDCHANGING;
           ::SetWindowPos(hBuddy, hAbove?hAbove:HWND_TOP, 0, 0, 0, 0,flag);

    }

    //测量试验滚动条的显隐状态是否变动,并因之调度模拟窗口的显隐状态

   //假使滚动条如故显得或滚动条某个因素的显得状态有变化或控件地方、尺寸也许改变,

   //强制重绘模拟窗口

    //......

    returnlReturn;

}

终极要拍卖WM_SHOWWINDOW和WM_DESTROY,当ListView遮蔽时让模拟窗口也随即消失;当它展现时,让模拟窗口也随后呈现。当ListView销毁时会触发WM_DESTROY,这时也须要销毁模拟窗口,那很关键。 

总的来说,模拟法是蛮麻烦的,但比较安全,可信性高。对开辟者来说,都是对音信举办一定处理,是正规手段,对最终顾客来讲,用此法达成的滚动条自绘,完全可以满意要求,具备丰硕的自由度,乃至能够对滚动条增加越多特定的效用,比如能够在下面增添别的按键,固然是加动画、加广告也都是足以的。

    //2)再在模拟窗口上绘制滚动条

    //......

    return 0;

}

别的还会有相当多任何的音讯或许引致滚动条属性的调换,如客户的键盘操作、鼠标滚轮操作恐怕形成滚动条的Thumb地方发生变动,这几个操作分别产生WM_KEYDOWN和WM_MOUSEWHEEL,而系统又在那多个消息中推行滚动条的绘图,由此你不可能不截获它们,但拍卖方法同WM_HSCROLL,这里不再啰嗦了。

当大家从没按下鼠标左键时,只是简短地在滚动条移动鼠标时,大家会开掘滚动条的按键和Thumb都会自行高亮,其实那一个变化都以系统在WM_NCMOUSEMOVE和WM_NCMOUSELEAVE中绘制达成的。比方当鼠标步向到Thumb上时,它就高亮了,当鼠标离开它,它又变橄榄黄了,你要分别管理WM_NCMOUSEMOVE和WM_NCMOUSELEAVE那多少个消息。注意唯有ListView应用大旨风格之后才或许有WM_NCMOUSELEAVE新闻,守旧风格的ListView就一贯不这么些音讯,独有WM_NCMOUSEMOVE音信,由此管理高亮还真有一些麻烦。正是因为大旨风格和价值观风格的出入,因而小编建议你也管理WM_THEMECHANGED音信,以识别不一样的核心模式,完结不相同高亮管理。看上边那几个图,TreeView的滚动条是主旨风格的,但ListView的滚动条是价值观风格的,但本人加了换肤功用。

除此以外,我们还应当拦截管理ListView的WM_NCPAINT,将滚动条的区域抠掉,不让它绘制滚动条。尽管滚动条被模仿窗口遮住了,但依旧有不可或缺如此做,以免止出现意外情形:

if(msg == WM_NCPAINT)

{

    HRGN wRgn = NULL; 

    RECT sbRect = GetScrollBarRect();//读取滚动条矩形的一个函数

    HRGN sRgn = ::CreateRectRgn(sbRect.left, sbRect.top, sbRect.right, sbRect.bottom

    if(wParam == 1)

    {

        RECT wRect;

        ::GetWindowRect(hListView, &wRect);

        wRgn = ::CreateRectRgn(wRect.left, wRect.top, wRect.right, wRect.bottom););

        wRgn = ::CombineRgn(wRng, wRgn, sRgn, RGN_DIFF);

    }

    else

    {

        wRgn = (HRGN)wParam; 

        wRgn = ::CombineRgn(wRng, wRgn, sRgn, RGN_DIFF);

    }

    ::DeleteObject(sRgn);

    ::CallWindowProc(gOldListViewProc, hListView, WM_NCPAINT, WPARAM(wRgn), 0);

    if(wParam == 1)

        ::DeleteObject(wRgn);

    return 0;

}

除此以外,还要拦截WM_WINDOWPOSCHANGING信息,因为当ListView的职位、尺寸、Z秩序爆发更动时要即刻调动模拟窗口的岗位、尺寸、Z秩序。为什么要在WM_WINDOWPOSCHANGING中开展,而不采纳在WM_WINDOWPOSCHANGED或WM_MOVE或WM_SIZE中开展呢?因为在WM_WINDOWPOSCHANGING中管理,可让模拟窗口先于ListView调度协和的职位、尺寸和Z,可防止有个别绘制难点。实际笔者在FreeCL中既用了WM_WINDOWPOSCHANGING,也用到WM_WINDOWPOSCHANGED四个消息。在管理WM_WINDOWPOSCHANGING时调节地方、尺寸、Z秩序,在拍卖WM_WINDOWPOSCHANGED时,强制重绘模拟窗口。

提起底还要验证一些的是,系统恐怕因为客商退换控件尺寸导致其滚动条自动消失或自行展现,也许调节滚动条的可用状态,如您拉宽支持多行彰显的Edit控件,会促成滚动条箭头按键变灰,Thumb消失。那几个动作平日都以在WM_WINDOWPOSCHANGED中完毕的,因而那些音信也急需拦截管理:

if(msg == WM_WINDOWPOSCHANGED)

{

    LRESULT lReturn = ::CallWindowProc(gOldListViewProc, hListView, WM_WINDOWPOSCHANGED,

        wParam, lParam);

    if(::GetNextWindow(hBuddy, GW_HWNDNEXT) != hListView)

    {   //调度模拟窗口的Z-Order,确定保证其紧贴ListView之上

        HWND hAbove = ::GetNextWindow(hListView, GW_HWNDPREV);

        UINT flag = SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOSENDCHANGING;
            ::SetWindowPos(hBuddy, hAbove?hAbove:HWND_TOP, 0, 0, 0, 0, flag);

    }

    //测量检验滚动条的显隐状态是还是不是改换,并因之调度模拟窗口的显隐状态

    //若是滚动条照旧显得或滚动条有个别因素的来得状态有调换或控件地点、尺寸恐怕改动,

    //强制重绘模拟窗口

    //......

    return lReturn;

}

最后要拍卖WM_SHOWWINDOW和WM_DESTROY,当ListView遮盖时让模拟窗口也随即死灭;当它显得时,让模拟窗口也随后展现。当ListView销毁时会触发WM_DESTROY,那时也亟需销毁模拟窗口,那很主要。 

总的来说,模拟法是蛮麻烦的,但比较安全,可相信性高。对开拓者来说,都以对消息实行一定管理,是正规花招,对最后客户来说,用此法达成的滚动条自绘,完全能够满意要求,具有丰富的自由度,以致能够对滚动条增添越多特定的功能,比方能够在上头增加别的开关,就算是加动画、加广告也都以能够的。

 

 

2  定制控件的背景颜色和背景位图的本事。

 

先是要说一下控件的绘图进程:当控件的某些区域要求重绘时,都会触发WM_ERASEBKGND和WM_PAINT新闻。比方控件的某部区域被另二个前后相继的窗口挡住了,而后那些窗口又被移走了,那时控件被遮挡的剧情就须求再行绘制了。

首先步:系统向控件发送WM_ERASEBKGND新闻以达成背景的擦除职业(临时不发送,比方顾客或者调用InvalidateRect(),其参数却钦定不擦除背景,那样就平素不这一个新闻);

第二步:系统向控件的窗口进度发送WM_PAINT信息,控件推行管理那些WM_PAINT音讯时会有选择地触发后边多少个步骤的动作;

其三步:对于有个别专门的学问控件,如Button、Edit、ListBox、ScrollBar、Static控件,它还有或者会向父窗口发送WM_CTLCOLORxxx(WM_CTLCOLORBUTTON、WM_CTLCOLOREDIT、WM_CTLCOLORSTATIC、WM_CTLCOLORLISTBOX、WM_CTLCOLO宝马X5SCROLLBA大切诺基等)的消息,那一个音讯重回一个刷子句柄,系统拿那几个刷子句柄进一步涂刷本身的背景。另外还发掘Trackbar也会向父窗口发送WM_CTLCOLO陆风X8STATIC新闻,TreeView在少数景况下也是有,但是作者未曾观察微软在什么样地点对那一点作注明;作者平常开掘众几人管理那些音信时,喜欢给系统重回三个NULL_BRUSH的空刷子,以为这么系统就不会把前边步骤画好的背景覆盖掉,其实不自然的,有个别控件不蒙蔽,某个就有毛病,像Trackbar正是那样,要小心。

第四步:对于菜单和好多正规控件,如Button、艾德it、ListBox、Static、ComboBox它或许会向父窗口发送WM_MEASUREITEM和WM_DRAWITEM音信,其它通用控件Tab、StatusBar、ListView、Header也恐怕会有WM_DRAWITEM新闻;但对此超过53%通用控件,如TreeView、ListView、Rebar、Trackbar、Toolbar等,它会向父窗口发送多数其ID为NM_CUSTOMDRAW的WM_NOTIFY音讯。对于那二种新闻,实际要求客户在曾经涂刷好的背景之上再实行本身的绘图职业;

第五步:当控件的WM_DRAWITEM或者WM_NOTIFY音讯未有被顾客管理时,系统会亲自实施自身的私下认可绘制专门的事业,把控件画出来,这一步未有艺术重载。

接头了那一个手续,大约大家心中早就清楚,知道怎样定制控件的背景颜色和背景位图了。平时景观下大家定制第一步、第三步完结和煦的特别背景,定制第四部实现控件本人的异样绘制。以致大家得以整个重载控件第一步的WM_ERASEBKGND音讯和第二步的WM_PAINT消息,控件背景和控件绘制全部和谐消除,没人说那样做老大。可是要细心,当自个儿达成WM_PAINT音信的重载管理时,前边3个步骤就都不发生了。

定制颜色倒是非常粗略,依据控件的品种管理WM_ERASEBKGND、WM_CTLCOLORxxx、WM_DRAWITEM、WM_NOTIFY音讯了,日常景色下,定制WM_ERASEBKGND和WM_CTLCOLORubiconxxx就能够了;对于背景位图比很多控件而不是常劳苦,像ListBox,你把背景位图涂刷好,结果因为用户操作滚动条或鼠标滚轮或按方向键,背景位图也时有产生滚动,那就不得不重绘位图,对于背景颜色就未有这几个主题素材,不管怎么滚动,颜色依然非常颜色,位图就可怜,须要本身重载发生滚动操作的种种音讯以促成位图重绘。微软就像并不倘让你会修改控件的背景位图,它未有对这一个场地作打算,总是一挥而就的对控件画布推行Scroll操作。真正贯彻背景位图的点子平时迫使大家要阻止那八个导致窗口内容爆发滚动的各个操作,由此位图背景的功用完毕也总让人以为有一些标准、不那么可信赖。

末段要注解的是:假使父控件还包括背景透明的子控件,你应有重载父控件的WM_ERASEBKGND音信,不然那一个透明背景的子控件大概就从未科学的背景内容。

上面这个步骤是本人个人的理解,不自然对哦!仅供参照他事他说加以考察。

 

3 完成控件的透明背景

  

众多情形下,我们须要控件的背景是晶莹的,正是须求直接看看控件父窗口的背景颜色、背景位图,举例标签控件、单选Radio控件、复选Check控件,经常都务求在父窗口的背景上实行绘图。不过须要控件的画布透明,那一个手艺在GDI的文书档案中从未见到Microsoft作其余表明,当然照旧有其余方法。

 

其一:倘若程序辅助桌面大旨服务以来,则可调用主旨服务的API来促成背景。大家先看看那些API:

HRESULT DrawThemeParentBackground(HWND hwnd, HDC hdc, RECT *prc);

这一个函数正是特意用来绘制父窗口的背景的,在那之中的hwnd参数是子窗口的句柄,hdc也时子窗口的画布句柄,prc是子窗口需绘制的区域,这几个函数实际是把父窗口的背景拷贝到子窗口上来,以这种格局到达透明。

 

其二:借使程序不协理桌面主题服务,则不可能运用方面包车型大巴主意,举个例子程序运行在Windows 3000上。那时大家得以向父窗口发送WM_PAINT音讯,可是此新闻所附带的wParam参数是三个画布句柄:

HDC dc = GetDC(NULL);

HWND cWnd = ...;//子窗口句柄

HWND pWnd = ...;//父窗口句柄

RECT cRect;

GetClientRect(cWnd, &cRect);

HBITMAP bitmap = CreateCompatibleBitmap(dc, cRect.right, cRect.bottom);

ReleaseDC(dc);

HDC memDC = CreateCompatibleDC(NULL);

HGDIOBJ oldBitmap = SelectObject(memDC, bitmap);

//此处可以调用SetClipRect()等函数来界定绘制范围

SendMessage(pWnd, WM_ERASEBKGND, (WPARAM)memDC, 0); 

SendMessage(pWnd, WM_PAINT, (WPARAM)memDC, 0);

//至此memDC上曾经保存了父窗口的背景内容

//顾客能够调用BitBlt(...)等函数拷贝memDC的故事情节到子窗口的某部区域,那样就直达了晶莹剔透效果;

SelectObject(memDC, oldBitmap);

DeleteDC(memDC); 

DeleteObject(bitmap);

上面的章程当然有限制,因为不是享有的父窗口都得以接受这种奇特的WM_PAINT音讯成效,但是MSDN中涉及大多数控件都有那些意义,我们要在乎读它的文书档案内容。

 

其三:如若上边的措施都不行的话,就剩下最笨的艺术了,用GDI函数涂刷子窗口的背景,但你事先将在精晓父窗口的背景颜色、背景位图等音讯。举个例子拿父窗口的颜料来填充子窗口的背景,能够调用FillRect()等:

//-------------------父窗口的背景是颜色的意况

COLO瑞鹰REF pColor = ...;//父窗口的颜色

HDC cDC = ...;//子窗口的画布句柄

RECT cRect = ...;//子窗口需刷新的区域 

HBRUSH brush = CreateSolidBrush(pColor);

FillRect(cDC, &cRect, brush);

DeleteObject(brush);

 

//-------------------父窗口的背景是位图的景况

HBITMAP pBitmap = ...;父窗口的背景位图

HDC cDC = ...;//子窗口的画布句柄

RECT cRect = ...;//子窗口需刷新的区域 

POINT rp;

SetBurshOrgEx(cDC, x, y, &rp);假如是位图刷子,则还索要调节画布的刷子原点偏移确定保证无缝

HBRUSH brush = CreatePatternBrush(pBitmap);

FillRect(cDC, &cRect, brush);

DeleteObject(brush);

SetBurshOrgEx(cDC, rp.x, rp.y, NULL);还原画布的刷子偏移

本文由澳门新葡萄京娱乐网站发布,转载请注明来源

关键词: