Windows系统提供大量的控件供我们使用,但是系统提供的控件样式都是统一的,不管什么东西看久了自然会厌烦,为了使界面更加美观,添加一些新的东西我们需要自己绘制控件。

控件在默认情况下并不进行自绘,如果是在窗口中利用CreateWindow创建的话要在风格中加入一个对应的自绘风格,这个一般在MSDN中都可以查到比如按钮的自绘风格是BS_OWNERDRAW、列表框是 LBS_OWNERDRAWFIXED (列表项的高度一致)、LBS_OWNERDRAWVARIABLE(列表项的高度可以不一致),如果我们是在对话框下通过资源的方式创建的可以在其属性上将自绘风格选上。控件被改为自绘时,每当需要自画时控件都会向其父窗口发送一条WM_DRAWITEM消息,该消息中两个参数的如下:

WM_DRAWITEM
idCtl = (UINT) wParam; // 控件ID
lpdis = (LPDRAWITEMSTRUCT) lParam; // 一个指向DRAWITEMSTRUCT的结构体

结构体DRAWITEMSTRUCT的定义如下:

typedef struct tagDRAWITEMSTRUCT {
UINT CtlType; //控件类型
UINT CtlID; //控件ID
UINT itemID; //控件子项的ID只用于菜单项、组合框、列表框
UINT itemAction; //控件行为,一般在一个动态的行为发生时产生
UINT itemState; //控件状态,在处于某个静态时产生
HWND hwndItem; //控件句柄
HDC hDC; //绘制控件的设备上下文句柄
RECT rcItem; //控件项的矩形范围
DWORD itemData; //程序为菜单项、列表项、组合框中的列表项指定的32值
} DRAWITEMSTRUCT;

对于列表框和组合框,在重绘时会发送一条消息:WM_MEASUREITEM,该消息用于设置列表项的大小信息。

可以在该消息中利用下面的代码设置行高:

LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam;
lpmis->itemHeight = 32;

下面来说说贴图。贴图的一般步骤为:

1)使用LoadBitmap加载一幅图片,该函数的原型为:

HBITMAP LoadBitmap(//函数返回一个对应位图的对象句柄
HINSTANCE hInstance, //实例句柄,系统通过这个值找到对应的位图
LPCTSTR lpBitmapName //位图名称,这个值可以通过MAKEINTRESOURCE宏获得
);

2)用CreateCompatiableDC函数创建一个与指定DC兼容的内存设备描述符。

3)利用SelectObject函数将对应位图选入到对应的HDC中,该函数返回一个原来未被替代的对象句柄,一般我们需要保存这个变量以便以后用于恢复。

4)使用BitBlt贴图

函数BitBlt,该函数的原型如下:

BOOL BitBlt(
HDC hdcDest, // 目的控件的设备上下文句柄
int nXDest, //
int nYDest, // 这两个参数表示需要贴在目的设备对应矩形中的哪个位置,分别是客户坐标的横坐标和纵坐标 int nWidth,
int nHeight, //图片的大小和宽度
HDC hdcSrc, // 源图片所在的DC的句柄
int nXSrc,
int nYSrc, //表示从原图片的哪个像素点开始,这两个值表示开始位置的横纵坐标
DWORD dwRop // 贴图的方式,它规定了原图片颜色如何与目标控件颜色组合已形成最终的颜色
);

对于第二步的操作并不是必要的,在贴图时我们可以使用同一个句柄作为原和目的句柄,但是当我们需要贴的图片过多,使用同一个句柄会造成客户区的闪烁,所以可以另外定义一个句柄,保存我们所需要的所有图片,然后一次性通过源DC贴到目的DC,这样可以一次完成,避免了客户区的闪烁。

下面的例子采用的是ListBox控件:

	HWND hList = CreateWindow("LISTBOX", "", WS_CHILD | WS_BORDER | WS_CLIPSIBLINGS  |WS_VISIBLE | LBS_HASSTRINGS | LBS_NOTIFY  | LBS_OWNERDRAWFIXED
, 0,0,200,800,hWnd, (HMENU)123, g_hInst, NULL);//在创建ListBox时定义为自画风格,同时WS_CLIPSIBLINGS风格指明在重绘子窗口时不重绘整个客户区

在WM_DRAWITEM消息中编写重绘的代码:

LPDRAWITEMSTRUCT lpDis = (LPDRAWITEMSTRUCT)lParam;
RECT rtListItem = lpDis->rcItem;
if (ODT_LISTBOX == lpDis->CtlType)
{
if (ODS_SELECTED & lpDis->itemState)//当某项被选中时设置虚线框并使背景为蓝色
{
rtListItem.right -= 2;
rtListItem.bottom -= 2;
HBRUSH hBlue = CreateSolidBrush(RGB(0,0,255));
HGDIOBJ hOld = SelectObject(lpDis->hDC, hBlue);
FillRect(lpDis->hDC, &rtListItem, hBlue);
DrawFocusRect(lpDis->hDC, &rtListItem);
}
	//贴图,并将图片背景色设置为所在矩形框的背景色
<span style="white-space:pre">	</span>HBITMAP  hBitMap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
HDC hMerDc= CreateCompatibleDC(lpDis->hDC);
SelectObject(hMerDc, hBitMap);
BitBlt(lpDis->hDC, lpDis->rcItem.left, lpDis->rcItem.top, lpDis->rcItem.right - lpDis->rcItem.left, lpDis->rcItem.bottom - lpDis->rcItem.top,
hMerDc, 0, 0, SRCAND);
SelectObject(lpDis->hDC,hBitMap);
DeleteObject(hMerDc);
<span style="white-space:pre">	</span>//将文字设置为透明、并显示文字
SetBkMode(lpDis->hDC, TRANSPARENT); DrawText(lpDis->hDC, g_Person[lpDis->itemID].pszName,strlen(g_Person[lpDis->itemID].pszName),
&(lpDis->rcItem),DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}

Windows程序设计学习笔记(四)自绘控件与贴图的实现的更多相关文章

  1. Windows程序设计学习笔记(1):一个简单的windows程序

    <Windows程序设计>(第五版)(美Charles Petzold著) #include<windows.h> LRESULT CALLBACK WndProc(HWND, ...

  2. Windows程序设计学习笔记(五)——菜单资源和加速键的使用

    菜单可能是Windows提供的统一用户界面中最重要的一种方式,菜单通常在标题栏的下一行显示,这一栏叫做菜单栏,菜单栏中的每一项称之为菜单项,菜单栏中的每一个菜单项在激活时会显现一个下拉菜单(也可以说是 ...

  3. Windows程序设计学习笔记(一)Windows内存管理初步

    学习Windows程序设计也有一些时间了,为了记录自己的学习成果,以便以后查看,我希望自己能够坚持写下一系列的学习心得,对自己学习的内容进行总结,同时与大家交流.因为刚学习所以可能有的地方写不不正确, ...

  4. Duilib学习笔记《03》— 控件使用

    在前面已经对duilib有个一个基本的了解,并且创建了简单的空白窗体.这仅仅只是一个开始,如何去创建一个绚丽多彩的界面呢?这就需要一些控件元素(按钮.文本框.列表框等等)来完善. 一. Duilib控 ...

  5. c#学习笔记之使用 TableLayoutPanel 控件设置窗体布局

    使用 TableLayoutPanel 控件设置窗体布局 在 Visual Studio IDE 左侧,找到“工具箱”选项卡. 选择“工具箱”选项卡,随即将显示工具箱.(或者,在菜单栏上,依次选择“视 ...

  6. 第六周学习笔记,vc各类控件的输入输出

    6w学习笔记 vc控件的输入输出 单选按钮 当单击 RadioButton 控件时,其 Checked 属性设置为 true,并且调用 Click 事件处理程序.当 Checked 属性的值更改时,将 ...

  7. Android Studio 学习笔记(三):简单控件及实例

    控件.组件.插件概念区分 说到控件,就不得不区分一些概念. 控件(Control):编程中用到的部件 组件(Component):软件的组成部分 插件(plugin): 应用程序中已经预留接口的组件 ...

  8. ODAC(V9.5.15) 学习笔记(二)控件列表

    ODAC的控件有26个,简单介绍如下: TOraSession  管理Oracle的连接  TOraQuery  使用SQL进行数据获取,自动将更新提交数据库  TSmartQuery    在处理字 ...

  9. IOS开发学习笔记019-动态创建控件

    动态创建控件 一.按钮 二.文本输入框 三.lable标签 注意: 只是简单的拖拽控件会毁了你,所以最好还是手动通过代码创建控件. 如果要通过代码生成按钮的话,可以在系统自带的函数viewDidLoa ...

随机推荐

  1. linux 开机批量启动程序

    每天早上到公司第一件事打开电脑,打开我的qq.我的开发工具idea.在看看邮件,日复一日,变懒了.也变聪明了,写了以下一段脚本 文件名称:mystart.sh #!bin/bash #检验我的开发工具 ...

  2. xml文档读取-SAX

    由于dom采用的是将xml文档加载入内存进行处理的方式,如果xml文档较大,则会导致加载时间过长,效率降低的情况,因此,sun公司在JAXP中又添加了对SAX的支持: SAX,全称Simple API ...

  3. iKcamp团队制作|基于Koa2搭建Node.js实战(含视频)☞ 路由koa-router

    路由koa-router--MVC 中重要的环节:Url 处理器

  4. mock.js的真实数据模拟

    哈哈,怎么说,这应该是我的第一个随笔了,毕竟前端之路上一直在学习并且各位大神们的经验,虽然也有不少的坑,但是总是收获比较多,所以我也想把一些收获记录下来,有需要的可以参考参考. 网上看了不少大神很多例 ...

  5. 六、Spring Boot Controller使用

    在Controller中使用 @RestController 注解,该注解是spring 4.0引入的.查看源码可知其包含了 @Controller 和 @ResponseBody 注解.我们可以理解 ...

  6. TP3.2.3 接入支付宝

    TP3.2.3 接入支付宝 项目接入支付宝支付了,在做这个给我的感觉是,方便 ,毕竟是老马的产品是吧, 话不多说 , 首先我们先找到官方的SDK  ,不想去找的小伙伴复制此链接 https://doc ...

  7. github上搜索资源

    1.进入官网 点击Explore 2.点击Trending 3.资源都在这上面,可以根据语言分类 4.搜索链接 https://github.com/trending

  8. 怎样在Spark、Flink应用中使用Protobuf 3的包

    如果在在Spark.Flink应用中使用Protobuf 3的包,因为Spark默认使用的是2.5版本的包,提交任务时,可能会报如下异常: com.google.protobuf.CodedInput ...

  9. MVC系列——一个异常消息传递引发的思考

    前言:最近在某个项目里面遇到一个有点纠结的小问题,经过半天时间的思索和尝试,问题得到解决.在此记录一下解决的过程,以及解决问题的过程中对.net里面MVC异常处理的思考.都是些老生常谈的问题,不多说, ...

  10. 52、css属性操作

    前面说的主要是css的使用规则和选择器等,这篇主要讲解css的具体使用. 一.css text 1.文本颜色:color 颜色属性被用来设置文字的颜色. 颜色是通过CSS最经常的指定: 1)十六进制值 ...