📄 button.c
字号:
/******************************************************
Copyright(c) 版权所有,1998-2003微逻辑。保留所有权利。
******************************************************/
/*****************************************************
文件说明:按钮类
版本号:1.0.0
开发时期:2000
作者:李林
修改记录:
******************************************************/
#include <eframe.h>
#include <esymbols.h>
#include <eassert.h>
//#include <gwmesrv.h>
#define GETTYPE( dwStyle ) ( (WORD)((dwStyle)&0xf) )
#define ICON_SIZE 16
#define GSB_CHECKNORMAL 0
#define GSB_CHECKSELECT 1
#define GSB_RADIONORMAL 2
#define GSB_RADIOSELECT 3
// 按钮标志
#define BTF_DISABLEFOCUS 0x0001
typedef struct _BUTTON_ATTRIB{
WORD btState; // OFFSET_STATE 0
WORD btFlag; // 按钮标志
HANDLE hImage; // OFFSET_IMAGE 4
COLORREF cl_Text;
COLORREF cl_TextBk; //正常文本的前景与背景色
COLORREF cl_Disable;
COLORREF cl_DisableBk; // 无效文本的前景与背景色
}BUTTON_ATTRIB, * PBUTTON_ATTRIB;
static void DoOwnerDraw( HDC, HWND hWnd, DWORD state, UINT uiAction );
static void DrawCheckState( HDC, HWND hWnd, DWORD state );
static void DrawPushState( HDC, HWND hWnd, BOOL fDefault, DWORD state );
static void DrawButtonState( HDC, HWND hWnd, DWORD style, DWORD state );
static LRESULT DoPAINT( HWND hWnd );
static LRESULT DoLBUTTONDOWN( HWND hWnd );
static LRESULT DoLBUTTONUP( HWND hWnd, short x, short y );
static LRESULT DoSETFOCUS( HWND hWnd );
static LRESULT DoSETSTATE( HWND hWnd, WPARAM wParam );
static LRESULT DoSETCHECK( HWND hWnd, WPARAM wParam );
static LRESULT WINAPI ButtonWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
// 类名
static const char strClassButton[] = "BUTTON";
// **************************************************
// 声明:ATOM RegisterButtonClass(HINSTANCE hInst)
// 参数:
// IN hInst - 实例句柄
// 返回值:
// 假如成功,返回非0值;失败,返回0
// 功能描述:
// 注册按钮类
// 引用:
// 被sysclass.c 调用
// ************************************************
// register my define class
ATOM RegisterButtonClass(HINSTANCE hInst)
{
WNDCLASS wc;
//初始化类结构
wc.hInstance=hInst;
wc.lpszClassName= strClassButton;
// the proc is class function
wc.lpfnWndProc=(WNDPROC)ButtonWndProc;
wc.style=CS_DBLCLKS|CS_CLASSDC;
wc.hIcon= 0;
// 基于笔的窗口,没有光标at pen window, no cursor
wc.hCursor= 0;//LoadCursor(NULL,IDC_ARROW);
// to auto erase background, must set a valid brush
// if 0, you must erase background yourself
wc.hbrBackground = 0;
wc.lpszMenuName=0;
wc.cbClsExtra=0;
// !!! it's important to save state of button, align to long
wc.cbWndExtra= sizeof( PBUTTON_ATTRIB );
return RegisterClass(&wc);
}
//#define SEND_NOTIFY( hParent, idCtrl, idNotify, hWnd ) \
// SendMessage( (hParent), WM_COMMAND, MAKELONG( (idCtrl), (idNotify) ), (LPARAM)(hWnd) )
// **************************************************
// 声明:static int SendNotify( HWND hParent, UINT uiId, UINT uiNotify, HWND hWnd )
// 参数:
// IN hParent - 父窗口
// IN uiId - 窗口id
// IN uiNotify - 通知消息
// IN hWnd - 窗口句柄
// 返回值:
// 依赖于具体的消息
// 功能描述:
// 向父窗口发送通知消息
// 引用:
//
// ************************************************
static int SendNotify( HWND hParent, UINT uiId, UINT uiNotify, HWND hWnd )
{
return SendMessage( hParent, WM_COMMAND, MAKELONG( uiId, uiNotify ), (LPARAM)hWnd );
}
// **************************************************
// 声明:static void FillSolidRect( HDC hdc, RECT * lprc, COLORREF clr )
// 参数:
// IN hdc - 显示设备句柄
// IN lprc - RECT 结构指针,指向需要填充的矩形
// IN clr - RGB颜色值
// 返回值:
// 无
// 功能描述:
// 用固定颜色填充举行矩形
// 引用:
//
// ************************************************
static void FillSolidRect( HDC hdc, RECT * lprc, COLORREF clr )
{
SetBkColor( hdc, clr );
ExtTextOut( hdc, 0, 0, ETO_OPAQUE, lprc, NULL, 0, NULL );
}
// **************************************************
// 声明:static void GetDrawRect( HDC hdc,
// LPCRECT lpClientRect,
// LPRECT lpTextRect,
// LPRECT lpIconRect,
// DWORD dwStyle )
// 参数:
// IN hdc - 显示设备句柄
// IN lpClientRect - 矩形指针,指向窗口的客户矩形
// OUT lpTextRect - 矩形指针,用于接受按钮的文本矩形
// OUT lpIconRect - 矩形指针,用于接受按钮的图标矩形
// IN dwStyle - 窗口风格
// 返回值:
// 无
// 功能描述:
// 得到按钮窗口的文本部分矩形和图标部分矩形
// 引用:
//
// ************************************************
static void GetDrawRect( HDC hdc, LPCRECT lpClientRect, LPRECT lpTextRect, LPRECT lpIconRect, DWORD dwStyle )
{
int type = GETTYPE( dwStyle ); // 得到按钮风格
*lpTextRect = *lpIconRect = *lpClientRect;
if( type == BS_DEFPUSHBUTTON ||
type == BS_PUSHBUTTON ||
(dwStyle & BS_PUSHLIKE) )
{ // 按钮风格
if( type == BS_DEFPUSHBUTTON )
{ // 默认按钮风格
InflateRect( lpTextRect, -1, -1 );
}
InflateRect( lpTextRect, -1, -1 );
}
else if( type == BS_RADIOBUTTON || type == BS_AUTORADIOBUTTON ||
type == BS_CHECKBOX || type == BS_AUTOCHECKBOX )
{ // 单选(自动)按钮 或 复选(自动)按钮
if( dwStyle & BS_LEFTTEXT )
{ // 按钮文本在左面, 象:[ ButtonText <icon> ]
lpIconRect->left = lpIconRect->right - ICON_SIZE;
lpTextRect->right = lpIconRect->left;// - 2;
}
else
{ // 按钮文本在右面, 象:[ <icon> ButtonText ]
lpIconRect->right = lpIconRect->left + ICON_SIZE;
lpTextRect->left = lpIconRect->right;// + 2;
}
// 设置图标的上下边
lpIconRect->top = ( lpClientRect->bottom + lpClientRect->top) / 2 - ICON_SIZE / 2;
lpIconRect->bottom = lpIconRect->top + ICON_SIZE;
}
else if( type == BS_GROUPBOX )
{ // 组框
TEXTMETRIC tm;
GetTextMetrics( hdc, &tm );
lpTextRect->left += 8;
lpTextRect->right -= 8;
lpTextRect->bottom = (short)(lpTextRect->top + tm.tmHeight);
}
}
// **************************************************
// 声明:static void DrawRadioBox( HDC hdc, LPCRECT lprectIcon, DWORD state )
// 参数:
// IN hdc - 显示设备句柄
// IN lprectIcon - 画单选按钮icon的矩形
// IN state - 单选按钮的状态
// 返回值:
// 无
// 功能描述:
// 画单选按钮
// 引用:
//
// ************************************************
static void DrawRadioBox( HDC hdc, LPCRECT lprectIcon, DWORD state )
{
int iOldMode;
BYTE bIcon;
HFONT hfont = SelectObject( hdc, GetStockObject(SYSTEM_FONT_SYMBOL) );
iOldMode = SetBkMode( hdc, TRANSPARENT );
if( state & BST_CHECKED )
bIcon = SYM_RADIO_SET;
else
bIcon = SYM_RADIO_NOSET;
DrawText( hdc, (LPCTSTR)&bIcon, 1, (LPRECT)lprectIcon, DT_CENTER|DT_VCENTER|DT_SINGLELINE );
SetBkMode( hdc, iOldMode );
SelectObject( hdc, hfont );
/*
HDC hMemDC;
HBITMAP hBitmap;
hMemDC = CreateCompatibleDC( hdc );
if( state & BST_CHECKED )
hBitmap = (HBITMAP)SelectObject( hMemDC, GetStockBitmap( GSB_RADIOSELECT ) );
else
hBitmap = (HBITMAP)SelectObject( hMemDC, GetStockBitmap( GSB_RADIONORMAL ) );
BitBlt( hdc, lprectIcon->left, lprectIcon->top, 8, 8, hMemDC, 0, 0, SRCCOPY );
SelectObject( hMemDC, hBitmap );
DeleteDC( hMemDC );
*/
}
// **************************************************
// 声明:static void DrawCheckBox( HDC hdc, LPCRECT lprectIcon, DWORD state )
// 参数:
// IN hdc - 显示设备句柄
// IN lprectIcon - 画icon的矩形
// IN state - 复选按钮的状态
// 返回值:
// 无
// 功能描述:
// 画复选按钮
// 引用:
//
// ************************************************
static void DrawCheckBox( HDC hdc, LPCRECT lprectIcon, DWORD state )
{
int iOldMode;
BYTE bIcon;
HFONT hfont = SelectObject( hdc, GetStockObject(SYSTEM_FONT_SYMBOL) );
iOldMode = SetBkMode( hdc, TRANSPARENT );
if( state & BST_CHECKED )
bIcon = SYM_CHECK_SET;
else
bIcon = SYM_CHECK_NOSET;
DrawText( hdc, (LPCTSTR)&bIcon, 1, (LPRECT)lprectIcon, DT_CENTER|DT_VCENTER|DT_SINGLELINE );
SetBkMode( hdc, iOldMode );
SelectObject( hdc, hfont );
/*
HDC hMemDC;
HBITMAP hBitmap;
hMemDC = CreateCompatibleDC( hdc );
if( state & BST_CHECKED )
hBitmap = (HBITMAP)SelectObject( hMemDC, GetStockBitmap( GSB_CHECKSELECT ) );
else
hBitmap = (HBITMAP)SelectObject( hMemDC, GetStockBitmap( GSB_CHECKNORMAL ) );
BitBlt( hdc, lprectIcon->left, lprectIcon->top, 8, 8, hMemDC, 0, 0, SRCCOPY );
SelectObject( hMemDC, hBitmap );
DeleteDC( hMemDC );
*/
}
// **************************************************
// 声明:static void DrawButtonState( HDC hdc, HWND hWnd, DWORD style, DWORD state )
// 参数:
// IN hdc - 显示设备句柄
// IN hWnd - 窗口句柄
// IN style - 窗口风格
// IN state - 状态
// 返回值:
// 无
// 功能描述:
// 画按钮(包含:check button, radio button...)
// 引用:
//
// ************************************************
static void DrawButtonState( HDC hdc, HWND hWnd, DWORD style, DWORD state )
{
WORD type = GETTYPE( style );
RECT rectClient, rectText, rectIcon;
HBRUSH hBrush;
PBUTTON_ATTRIB pAttrib = (PBUTTON_ATTRIB)GetWindowLong( hWnd, 0 ); // 得到按钮属性结构指针
BOOL bEnable = IsWindowEnabled( hWnd ); //
char strBuf[128];
char * buf = NULL;
int l, shift = 0;
WORD textStyle = 0;
GetClientRect( hWnd, &rectClient ); // 得到窗口客户矩形
l = GetWindowTextLength( hWnd ); // 得到窗口文本长度
if( l < sizeof( strBuf ) )
{
l = GetWindowText( hWnd, strBuf, sizeof( strBuf ) ); // 得到窗口文本
buf = strBuf;
}
else
{ // 窗口文本太大,动态分配一个
l = (l + 1 )* sizeof( char );
buf = malloc( l );
if( buf )
{
GetWindowText( hWnd, buf, l );
}
else
return;
}
textStyle = DT_SINGLELINE | DT_VCENTER;
// 用背景色填充
if( bEnable )
FillSolidRect( hdc, &rectClient, pAttrib->cl_TextBk ); // clear background
else
FillSolidRect( hdc, &rectClient, pAttrib->cl_DisableBk ); // clear background
// 选择空刷子
hBrush = SelectObject( hdc, GetStockObject( NULL_BRUSH ) );
GetDrawRect( hdc, &rectClient, &rectText, &rectIcon, style );
if( type == BS_DEFPUSHBUTTON ||
type == BS_PUSHBUTTON ||
(style & BS_PUSHLIKE) )
{ // 按钮
textStyle |= DT_CENTER;
// 画边界矩形
if( type == BS_DEFPUSHBUTTON )
{
Rectangle( hdc, rectClient.left, rectClient.top, rectClient.right, rectClient.bottom );
}
if( state & (BST_PUSHED|BST_CHECKED) ) // highlight state( sunken or checked )
{ //
DrawEdge( hdc, &rectClient, BDR_SUNKENOUTER, BF_RECT );
shift = 1;
}
else // normal state
DrawEdge( hdc, &rectClient, BDR_RAISEDOUTER, BF_RECT );
}
else if( type == BS_RADIOBUTTON || type == BS_AUTORADIOBUTTON )
DrawRadioBox( hdc, &rectIcon, state ); // 单选按钮
else if( type == BS_CHECKBOX || type == BS_AUTOCHECKBOX )
DrawCheckBox( hdc, &rectIcon, state ); // 复选按钮
else if( type == BS_GROUPBOX )
{ // 组框
textStyle |= DT_CENTER;
rectClient.top += (rectText.bottom - rectText.top) / 2;
// 画边框
DrawEdge( hdc, &rectClient, BDR_SUNKENOUTER, BF_RECT ); //
// 缩小边框一个点宽
InflateRect( &rectClient, -1, -1 );
// 画边框
DrawEdge( hdc, &rectClient, BDR_RAISEDOUTER, BF_RECT ); //
// 缩小边框一个点宽
InflateRect( &rectClient, -1, -1 );
}
if( (state & BST_FOCUS) && type != BS_GROUPBOX )
{ // 按钮有焦点 has focus
DrawFocusRect( hdc, &rectText );
//InflateRect( &rectText, -1, -1 ); // 2003-06-19, DEL, 这行将使文本产生抖动
}
if( shift ) // move down state
{ // 使文本产生向下移动的视觉感
rectText.left += 1;
rectText.top += 1;
}
// draw text or image
if( style & (BS_BITMAP | BS_ICON) )
{ // 图象位图按钮
HANDLE hSave, hImage = pAttrib->hImage;
if( hImage )
{
if( style & BS_BITMAP )
{ // 位图 BITMAP
HDC hMemDC = CreateCompatibleDC( hdc ); // 创建内存DC
hSave = SelectObject( hMemDC, hImage ); // 为内存DC选择输出面
// 贴图
BitBlt(
hdc,
rectText.left,
rectText.top,
rectText.right - rectText.left,
rectText.bottom - rectText.top,
hMemDC,
0,
0,
SRCCOPY
);
// 恢复
hSave = SelectObject( hMemDC, hSave );
DeleteDC( hMemDC );
}
else
{ // 图标 ICON
DrawIcon( hdc, rectText.left, rectText.top, hImage );
}
}
}
else
{ // 文本按钮
// 检查对齐模式并设置文本输出格式
if( (style & BS_CENTER) == BS_CENTER )
{
textStyle |= DT_CENTER; // 居中
}
else
{
if( style & BS_LEFT )
{
textStyle &= ~DT_CENTER;
textStyle |= DT_LEFT; // 左对齐
}
else if( style & BS_RIGHT )
{
textStyle &= ~DT_CENTER;
textStyle |= DT_RIGHT; // 右对齐
}
}
if( (style & BS_VCENTER) == BS_VCENTER )
{
textStyle |= DT_VCENTER; // 垂直对齐
}
else
{
if( style & BS_TOP )
{
textStyle &= ~DT_VCENTER;
textStyle |= DT_TOP; // 上对齐
}
else if( style & BS_BOTTOM )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -