VC++ WIN32 sdk实现按钮自绘详解.

#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 ...
- 微信支付PHP SDK —— 公众号支付代码详解
在微信支付 开发者文档页面 下载最新的 php SDK http://mch.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 这里假设你已经申请完微 ...
- VC中预处理指令与宏定义详解
刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...
- 转:VC解析XML文件-CMarkup的使用详解
本篇文章是对VC解析XML文件-CMarkup的使用进行了详细的分析介绍,需要的朋友参考下 VC解析XML文件的工具有很多,CMarkup, tinyXML,还有IBM的,MS的等等. 据说tinyX ...
- 【转】android SDK中的ddms使用详解
一.查看线程信息1.展开左侧设备节点,选择进程: 2.点击更新线程信息图标: 注意:如果你没有运行或调试程序的话,这些图标是不可用的! 3.右侧选择“Threads”标签: 二.查看堆栈信息1.展开左 ...
- Engine工具栏按钮的使用详解
转自原文 Engine自定义控件实现toolbar功能 Engine提供的工具条能够轻易实现各种操作,非常方便,可是不好的地方就是太死板了,toolbar的图标都不能改.因此需要自己做按钮做控件去实现 ...
- Python连载60-Tkinter布局、按钮以及属性详解
一.Tkinter 1.组件的大致使用步骤 (1)创建总面板 (2)创建面板上的各种组件: i.指定组件的父组件,即依附关系:ii.利用相应的属性对组件进行设置:iii.给组件安排布局. (3)同步 ...
随机推荐
- 增进离岸Java开发效率的10个提示
本文来源于我在InfoQ中文站原创的文章,原文地址是:http://www.infoq.com/cn/news/2013/12/10-tips-offshore-java-effective Cygn ...
- W3C 、HTML 、CSS 发展介绍
一.W3C W3C 指万维网联盟(World Wide Web Consortium),创建于1994年10月,由 Tim Berners-Lee (他是html的发明人)创建. W3C开始被创建的目 ...
- c++ - Create empty json array with jsoncpp - Stack Overflow
python中multiprocessing.pool函数介绍_正在拉磨_新浪博客 multiprocessing.pool c++ - Create empty json array wit ...
- Debian为程序添加一个开始菜单,debian添加sublime开始菜单.
下了一个 '绿色' 的程序,想要加到开始菜单里面. 怎么做呢? 我这里以sublime2做例 去http://www.sublimetext.com/2 下载了linux 64位, 解压放到了下面的文 ...
- 查看linux下各数据类型的大小
代码如下: #include<stdio.h> int main() { printf("int:%d bytes\n",sizeof(int)); printf(&q ...
- weblogic中设置数据源的注意点
一.基本概念 进入weblogic的管理页面,点击服务——>数据源,可以进行数据源的配置.通过新建,输入地址,用户名,密码等信息可以新建一个数据源. 二.发现问题 建立好数据源之后,跑项目,发现 ...
- java--内部类访问final成员
局部类只能访问外包方法中的final成员.位于方法内部的局部类,可以访问局部类之外,外包方法之内的所以变量和方法,但是生命周期不同,延长生命周期的办法就是将变量设置为final类型. 1)从程序设计语 ...
- KestrelServer
KestrelServer 跨平台是ASP.NET Core一个显著的特性,而KestrelServer是目前微软推出了唯一一个能够真正跨平台的Server.KestrelServer利用一个名为Ke ...
- SuperSocket源码解析之启动过程
一 简介 这里主要说明从配置系统引导启动SuperScoekt作为应用程序,且以控制台程序方式启动 二 启动过程 2.1 配置解析 从读取配置文件开始,直接拿到一个SocketServiceConfi ...
- 配置Jenkins的slave节点的详细步骤适合windows等其他平台(转)
@ 新建一个slave节点在Jenkins服务器上 1,进入Jenkins的主界面,进入“Manage Jenkins” 页面: 2,点击如下图中的“Manage Nodes”: 3,进入页面后点 ...