#include "resource.h"
HWND hMainWnd = NULL; //接收主窗口的句柄
HWND hDlgNow = NULL; //接收对话框的句柄
static HICON hOwnerDrawIcon = NULL; //用作自绘按钮的图标
static LONG prev_proc; //储存按钮先前的回调函数
static HICON hIcon = NULL; //对话框图标句柄
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
odInst = hInstance;
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)ODWndProc; //定义一个窗口默认函数,这里我们会交由默认窗口函数处理
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(odInst,MAKEINTRESOURCE(IDI_OWNERDRAW));
wc.hCursor = NULL;
wc.hbrBackground = 0;
wc.lpszClassName = "OwnerDraw";
wc.lpszMenuName = NULL;
RegisterClass(&wc);
MSG msg;
HWND onlywin= FindWindow("OwnerDraw","MyOwnerDraw");
if (onlywin)
{
ExitProcess(1);
}
hMainWnd=CreateWindow("OwnerDraw","MyOwnerDraw",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
if (!hMainWnd)
{
return FALSE;
}
hDlgNow = DoMainDlg(hMainWnd);
ShowWindow(hDlgNow, nCmdShow);
while(GetMessage(&msg, NULL, 0, 0))
{
if (NULL == hDlgNow || !IsDialogMessage(hDlgNow, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
{
return DefWindowProc(hWnd, message, wParam, lParam);//返回系统默认的窗口过程
}
if (onlywin)
{
ExitProcess(1);
}
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
ShowWindow(hDlgNow, nCmdShow);
{
DWORD dwErr;
HWND hRet = CreateDialog(odInst, (LPCTSTR)IDD_MAIN_DLG, parent, (DLGPROC)MainDlgProc);
if(hRet == NULL)
dwErr = GetLastError();
return hRet;
}
{
if (NULL == hDlgNow || !IsDialogMessage(hDlgNow, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if(hIcon == NULL)
hIcon = LoadIcon(odInst, MAKEINTRESOURCE(IDI_OWNERDRAW));
if(hOwnerDrawIcon == NULL)
hOwnerDrawIcon = (HICON)LoadImage(odInst,
MAKEINTRESOURCE(IDI_OWNERDRAW),
IMAGE_ICON,
38,
38,
0);
prev_proc = SetWindowLongPtr(GetDlgItem(hDlg, IDC_ODBUTTON), GWLP_WNDPROC, (LONG)ButtWindProc);
SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
SetFocus(GetDlgItem(hDlg, IDC_ODBUTTON));
break;
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 10, "System"
BEGIN
DEFPUSHBUTTON "OK",IDOK,193,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,193,24,50,14
CONTROL "OwnerDraw",IDC_ODBUTTON,"Button",BS_OWNERDRAW |
WS_TABSTOP,49,31,79,26
END
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) lParam;
//声明一个指向DRAWITEMSTRUCT结构体的指针并将其指向存储着按钮构造信息的lParam
if(lpDIS->CtlID != IDC_ODBUTTON)
return (0);
HDC dc = lpDIS->hDC; //用于按钮绘制的DC
BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED);
BOOL bIsFocused = (lpDIS->itemState & ODS_FOCUS);
BOOL bIsDisabled = (lpDIS->itemState & ODS_DISABLED);
BOOL bDrawFocusRect = !(lpDIS->itemState & ODS_NOFOCUSRECT);
//判断按钮各种状态的BOOL值
RECT itemRect = lpDIS->rcItem; //按钮的矩形区域
SetBkMode(dc, TRANSPARENT); //设置绘制按钮时的背景状态
if (bIsFocused) //判断按钮是否获得了焦点并对其边框进行处理
{
HBRUSH br = CreateSolidBrush(RGB(0,0,0));
FrameRect(dc, &itemRect, br);
InflateRect(&itemRect, -1, -1);
DeleteObject(br);
} // if
COLORREF crColor = GetSysColor(COLOR_BTNFACE);//得到系统按钮颜色
HBRUSH brBackground = CreateSolidBrush(crColor);//创建画刷
FillRect(dc, &itemRect, brBackground);//绘制按钮
DeleteObject(brBackground);
// 这里画被按下去的按钮
if (bIsPressed)
{
HBRUSH brBtnShadow = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
FrameRect(dc, &itemRect, brBtnShadow);
DeleteObject(brBtnShadow);
}
else //如果没有被按下就这样画
{
UINT uState = DFCS_BUTTONPUSH |
((bIsPressed) ? DFCS_PUSHED : 0);
DrawFrameControl(dc, &itemRect, DFC_BUTTON, uState);
}
char sTitle[100];
GetWindowText(GetDlgItem(hDlg, IDC_ODBUTTON), sTitle, 100);//得到按钮的文本
RECT captionRect = lpDIS->rcItem;//把文本的区域设置为按钮区域
BOOL bHasTitle = (sTitle[0] !='/0');//按钮上是否有文本存在
//这里画按钮上的图标,具体实现见下面
(GetDlgItem(hDlg, IDC_ODBUTTON), &dc, bHasTitle,
&lpDIS->rcItem, &captionRect, bIsPressed, bIsDisabled);
if (bHasTitle)//如果按钮有文本标题
{
// 按钮被按下的处理
if (bIsPressed)
OffsetRect(&captionRect, 1, 1);
// 将文本居中
RECT centerRect = captionRect;
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CALCRECT|DT_CENTER);
LONG captionRectWidth = captionRect.right - captionRect.left;
LONG captionRectHeight = captionRect.bottom - captionRect.top;
LONG centerRectWidth = centerRect.right - centerRect.left;
LONG centerRectHeight = centerRect.bottom - centerRect.top;
OffsetRect(&captionRect, (centerRectWidth - captionRectWidth)/2, (centerRectHeight - captionRectHeight)/2);
SetBkMode(dc, TRANSPARENT);
if (bIsDisabled)//如果按钮被禁用
{
OffsetRect(&captionRect, 1, 1);
SetTextColor(dc, ::GetSysColor(COLOR_3DHILIGHT));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
OffsetRect(&captionRect, -1, -1);
SetTextColor(dc, ::GetSysColor(COLOR_3DSHADOW));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
}
else //如果没被禁用正常画
{
SetTextColor(dc, ::GetSysColor(COLOR_BTNTEXT));
SetBkColor(dc, ::GetSysColor(COLOR_BTNFACE));
DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER);
}
}
// 画按钮得到焦点时的虚线方框
if (bIsFocused && bDrawFocusRect)
{
RECT focusRect = itemRect;
InflateRect(&focusRect, -3, -3);
DrawFocusRect(dc, &focusRect);
} // if
return (TRUE);
}
break;
{
RECT rImage;
PrepareImageRect(hButtonWnd, bHasTitle, rpItem, rpTitle, bIsPressed, 38, 38, &rImage);
// 调用API函数按准备好的形式将图片画到按钮上
DrawState( *dc,
NULL,
NULL,
(LPARAM)hOwnerDrawIcon,
0,
rImage.left,
rImage.top,
(rImage.right - rImage.left),
(rImage.bottom - rImage.top),
(bIsDisabled ? DSS_DISABLED : DSS_NORMAL) | DST_ICON);
}
{
RECT rBtn;
CopyRect(rpImage, rpItem);
GetClientRect(hButtonWnd, &rBtn);
if (bHasTitle == FALSE)//如果按钮上有文本内容
{
// 使图片水平居中
LONG rpImageWidth = rpImage->right - rpImage->left;
rpImage->left += ((rpImageWidth - (long)dwWidth)/2);
}
else
{ //控制图片与焦点方框内部
LONG rpTitleWidth = rpTitle->right - rpTitle->left;
rpTitle->right = rpTitleWidth - dwWidth - 30;
rpTitle->left = 30;
rpImage->left = rBtn.right - dwWidth - 22;
LONG rpImageHeight = rpImage->bottom - rpImage->top;
rpImage->top += ((rpImageHeight - (long)dwHeight)/2);
}
if (bIsPressed)//按钮被按下的处理
OffsetRect(rpImage, 1, 1);
}
HWND hWnd, //window handle
UINT message, // type of message
WPARAM wParam, // additional information
LPARAM lParam) //additional information
{
switch (message)
{
case WM_LBUTTONDBLCLK:
PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam);
break;
}
//将不做处理的消息路由给原默认函数
return CallWindowProc((WNDPROC)prev_proc, hWnd, message, wParam, lParam);
}
DefWindowProc(hDlg, message, wParam, lParam);
break;
case WM_SYSCOMMAND:
{
return DefWindowProc(hDlg, message, wParam, lParam);
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
DestroyIcon(hOwnerDrawIcon);
PostQuitMessage(0);
return TRUE;
}//switch
break;
VC++ WIN32 sdk实现按钮自绘详解 之二.的更多相关文章
-
VC++ WIN32 sdk实现按钮自绘详解 之二(关键是BS_OWNERDRAW和WM_DRAWITEM)
网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片: 首先建立一个标准的Win32 Application 工程.选择a simple Wi ...
-
VC++ WIN32 sdk实现按钮自绘详解.
网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片: 首先建立一个标准的Win32 Application 工程.选择a simple Wi ...
-
vc中调用Com组件的方法详解
vc中调用Com组件的方法详解 转载自:网络,来源未知,如有知晓者请告知我.需求:1.创建myCom.dll,该COM只有一个组件,两个接口: IGetRes--方法Hello(), IGet ...
-
Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能
Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSD ...
-
WebView使用详解(二)——WebViewClient与常用事件监听
登录|注册 关闭 启舰 当乌龟有了梦想…… 目录视图 摘要视图 订阅 异步赠书:Kotlin领衔10本好书 免费直播:AI时代,机器学习如何入门? 程序员8 ...
-
OutputCache属性详解(二)一 Location
目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...
-
ViewPager 详解(二)---详解四大函数
前言:上篇中我们讲解了如何快速实现了一个滑动页面,但问题在于,PageAdapter必须要重写的四个函数,它们都各有什么意义,在上节的函数内部为什么要这么实现,下面我们就结合Android的API说明 ...
-
html 05-HTML标签图文详解(二)
05-HTML标签图文详解(二) #本文主要内容 列表标签:<ul>.<ol>.<dl> 表格标签:<table> 框架标签及内嵌框架<ifram ...
-
RocketMQ详解(二)安装使用详解
专题目录 RocketMQ详解(一)原理概览 RocketMQ详解(二)安装使用详解 RocketMQ详解(三)启动运行原理 RocketMQ详解(四)核心设计原理 RocketMQ详解(五)总结提高 ...
随机推荐
-
Hadoop 之Mong DB 之CentOS 6 使用 yum 安装MongoDB及服务器端配置
安装MongoDB的方法有很多种,可以源代码安装,在Centos也可以用yum源安装的方法.由于MongoDB更新得比较快,我比较喜欢用yum源安装的方法.64位Centos下的安装步骤如下: 1.准 ...
-
windbg配置问题汇总
.loadby sos.dll mscorwks.symfix c:\windows\symbols windbg配置问题汇总 1.Failed to find runtime DLL (clr.dl ...
-
python 网络编程(一)---基础
1.理解TCP 1.1 寻址 首先任何基于TCP/IP的网络,每台机器都有唯一的IP地址,只需要知道接受者机器的IP地址,信息就可以传送过去. 其次,TCP通过使用端口号来知道机器究竟是哪个程序应该接 ...
-
不同框架实现的WebService的服务端获取HttpServletRequest的方法
一. 基于xfire实现的WebService HttpServletRequest request = XFireServletController.getRequest(); 二. 基于axis实 ...
-
Swift基础语法学习总结二
1.函数 1.1 func funcNmae()->(){} 这样就定义了一个函数,它的参数为空,返回值为空,如果有参数和返回值直接写在两个括号里就可以了 1.2 参数需要指明类型,而如果没有返 ...
-
剖析Jetty实现原理
之前写一个简单易用Jetty文章.Jetty对于做JAVA Web发展的方面来说并不陌生,他是一个servlet集装箱,只有相对Tomcat这是比较简单的设计,并且也相对简单,使用灵活,我是学习和使用 ...
-
LPC1768的usb使用--硬件篇
LPC1768芯片带有USB设备控制器,前面写的文章都是在说比较简单的设备驱动,今天来说复杂一点的 首先是硬件层的配置 #ifndef __USBHW_H__ #define __USBHW_H__ ...
-
[UVa 1326]Jurassic Remains
题解 在一个字符串中,每个字符出现的次数本身是无关紧要的,重要的只是这些次数的奇偶性,因此想到用一个二进制的位表示一个字母($1$表示出现奇数次,$0$表示出现偶数次).比如样例的$6$个数,写成二进 ...
-
06 爬虫框架:scrapy
爬虫框架:scrapy 一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前S ...
- JSPGen4 自学路线图