#define _WIN32_WINNT 0x0400
#include "WTaber.h"
#include "FShare.h"
#include "wflList.h"
#include "commctrl.h"
//////////////////////////////////////////////////////////////////////////////////
//function declare
static LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
static WNDCLASSEX taber;
void RegWTaber(HINSTANCE hInstance){
taber.cbClsExtra = 0;
taber.cbSize = sizeof(WNDCLASSEX);
taber.cbWndExtra = 4;
taber.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
taber.hCursor = LoadCursor(NULL,IDC_ARROW);
taber.hIcon = NULL;
taber.hIconSm = 0;
taber.hInstance = hInstance;
taber.lpfnWndProc = (WNDPROC)WndProc;
taber.lpszClassName = "WTaber";
taber.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&taber);
};
////////////////////////////////////////////////////////////////////////////////////////////
//function declared map of WM_ MSGS;
static LRESULT OnPaint(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnCreate(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnWTaberCommand(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnRButtonDown(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnRButtonUp(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnLButtonDown(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnLButtonUp(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnMouseMove(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnMouseLeave(HWND,UINT,WPARAM,LPARAM);
static LRESULT OnMouseWheel(HWND,UINT,WPARAM,LPARAM);
////////////////////////////////////////////////////////////////////////////////////////////
//user data (用宏定义链表虽然方便,可看起来真是没有风格。)
STRUCT_NEW_NODE(TAB)
char* szCaption; //页标题
RECT stBound; //大小 :窗体风格也許是THICKFRAME,所以要动态变更。
RECT stClient; //客户区大小,绘制文本的地方 - 根据stBound计算
BYTE FLAG; //標記:是否激活狀態
STRUCT_END_NODE(TAB)
STRUCT_NEW_LIST(TABS,TAB)
STRUCT_END_LIST(TABS)
DECLARE_LIST_FUNC(TABS,TAB)
///////////////////////////////////////////////////////////////////////////////////////////////
//这个用来表示内部成员数据
typedef struct _WTABERMEMBERS{
TABS* tabs; //页链表
HWND hwnd; //保存WTABER控件的句柄,(方便全局调用 :)
UINT pos; //繪製成員的開始位置
HWND FOwner; //在WTABER獲得焦點之前,先記錄擁有鼠標焦點的控件
TAB* posTab; //繪製TAB成員時的標誌
}WTABERMEMBER;
static WTABERMEMBER member;
///////////////////////////////////////////////////////////////////////////////////////////////
static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
switch(msg){
case WM_CREATE:
OnCreate(hwnd,msg,wParam,lParam);
break;
case WM_PAINT:
OnPaint(hwnd,msg,wParam,lParam);
break;
case WTABER_COMMAND:
return OnWTaberCommand(hwnd,msg,wParam,lParam);
break;
case WM_RBUTTONDOWN:
OnRButtonDown(hwnd,msg,wParam,lParam);
break;
case WM_RBUTTONUP:
OnRButtonUp(hwnd,msg,wParam,lParam);
break;
case WM_ERASEBKGND:
return TRUE;
break;
case WM_LBUTTONUP:
OnLButtonUp(hwnd,msg,wParam,lParam);
break;
case WM_LBUTTONDOWN:
OnLButtonDown(hwnd,msg,wParam,lParam);
break;
case WM_MOUSEMOVE:
OnMouseMove(hwnd,msg,wParam,lParam);
if ( GetFocus() != hwnd ){
member.FOwner = GetFocus();
SetFocus(hwnd);
}
break;
case WM_MOUSEWHEEL:
OnMouseWheel(hwnd,msg,wParam,lParam);
break;
case WM_MOUSELEAVE:
OnMouseLeave(hwnd,msg,wParam,lParam);
break;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
return 0;
};
////////////////////////////////////////////////////////////////////////////////
static WTABER* _COMMAND;
////////////////////////////////////////////////////////////////////////////////
//刷新操作
static void SelfRefresh(HWND hwnd){
RECT rect;
GetClientRect(hwnd,&rect);
InvalidateRect(hwnd,&rect,TRUE);
}
//判斷座標是否在一個矩形內
static BOOL SelfPointAt(POINT p,RECT r){
return ( r.left <= p.x && p.x <= r.right && r.top <= p.y && p.y <= r.bottom );
}
static RECT SelfRect(HWND hwnd){
RECT rect;
GetClientRect(hwnd,&rect);
return rect;
}
// * 根據TAB'句柄'重新ACTIVE頁面
static void SelfActiveTab(UINT tabPtr){
static void SelfScrollTab(UINT);
TAB* tab;
FOREACH_BEGIN(member.tabs,tab)
tab->FLAG = 0;
FOREACH_END(tab);
(*(TAB*)tabPtr).FLAG = 1;
// * 如果當前頁面不可視,則滾動視圖
if ( (*(TAB*)tabPtr).stBound.right > SelfRect(member.hwnd).right ){
// * 設置當前繪製頁 _ _ _ posTab
member.posTab = (TAB*)tabPtr;
SelfScrollTab( (UINT)(member.posTab) );
SelfRefresh(member.hwnd);
}
}
// * 根據TAB'句柄'重新滾動繪製TAB項 * 使用該函數傳member成員posTab
static void SelfScrollTab(UINT tabPtr){
// * 這個函數是自己內部操作的,可以肯定tabPtr不是空指向
TAB* tab = (TAB*)tabPtr;
member.pos = member.tabs->HEAD->stBound.left - tab->stBound.left + 2;
}
static void SelfDrawDKGRND(HDC dc,RECT rect){
int TX,TY;
for ( TX = rect.left ; TX <= rect.right ; TX+=2) {
for ( TY = rect.top ; TY <= rect.bottom ; TY+=2 ){
if ( TY % 2 == 0 ){
MoveToEx(dc,TX,TY,NULL);
LineTo(dc,TX+2,TY+2);
}
}
}
}
//新建頁;返回新建頁面‘句柄’
static LONG SelfNewPage(LPSTR lpCaption){
TAB* tab = TAB_NEW();
tab->szCaption = lpCaption;
tab->FLAG = 0;
TABS_APPEND(member.tabs,tab);
SelfRefresh(member.hwnd);
return (LONG)tab;
};
//绘制TAB成员,
static void SelfDrawTabs(HDC dc){
TAB* tab;
RECT rect;
SIZE size;
GetClientRect(member.hwnd,&rect);
FOREACH_BEGIN(member.tabs,tab)
GetTextExtentPoint32(dc,(*tab).szCaption,strlen((*tab).szCaption)+1,&size);
if ( tab == member.tabs->HEAD ) {
(*tab).stBound.left = member.pos;
(*tab).stBound.right = (*tab).stBound.left + size.cx + 30;
(*tab).stBound.top = rect.top + 2;
(*tab).stBound.bottom = rect.bottom - 2;
}else{
TAB* pre = (*tab).PREV;
(*tab).stBound.left = (*pre).stBound.right + 2;
(*tab).stBound.right = (*tab).stBound.left + size.cx + 30;
(*tab).stBound.top = (*pre).stBound.top;
(*tab).stBound.bottom = (*pre).stBound.bottom;
}
//計算TAB客戶區大小
{
(*tab).stClient.left = (*tab).stBound.left + 2;
(*tab).stClient.top = (*tab).stBound.top + 2;
(*tab).stClient.right = (*tab).stBound.right - 2;
(*tab).stClient.bottom = (*tab).stBound.bottom - 2;
}
if( (*tab).FLAG == 1 ){
HPEN nP,oP;
HBRUSH nB,oB;
nB = CreateHatchBrush(HS_DIAGCROSS,GetSysColor(COLOR_BTNFACE));
nP = CreatePen(1,PS_SOLID,RGB(255,255,255));
oP = SelectObject(dc,nP);
oB = SelectObject(dc,nB);
DrawEdge(dc,&((*tab).stBound),EDGE_SUNKEN,BF_RECT);
SetBkMode(dc,BKMODE_LAST);
SelfDrawDKGRND(dc,(*tab).stClient);
SetBkMode(dc,TRANSPARENT);
DeleteObject(SelectObject(dc,oB));
DeleteObject(SelectObject(dc,oP));
}
else{
DrawEdge(dc,&((*tab).stBound),EDGE_ETCHED,BF_RECT);
}
DrawText(dc,(*tab).szCaption,-1,&((*tab).stClient),DT_SINGLELINE | DT_CENTER | DT_VCENTER);
FOREACH_END(tab);
};
static LRESULT OnCreate(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
member.tabs = TABS_NEW();
member.hwnd = hwnd;
member.pos = 2;
member.posTab = NULL;
return 0;
};
static LRESULT OnPaint(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
PAINTSTRUCT ps;
HBITMAP MemBmp;
HDC SrcDc;
HDC MemDc; //內存DC
RECT rect;
HFONT oFont;
GetClientRect(hwnd,&rect);
SrcDc = BeginPaint(hwnd,&ps);
MemDc = CreateCompatibleDC(SrcDc);
MemBmp = CreateCompatibleBitmap(SrcDc,rect.right + 1,rect.bottom);
//雙緩衝繪製圖形
SelectObject(MemDc,MemBmp);
SetBkColor(MemDc,GetBkColor(SrcDc));
{
//繪製背景色 COLOR_BTNFACE
LOGBRUSH lb;
HBRUSH ob;
HPEN oP;
lb.lbColor = GetSysColor(COLOR_BTNFACE);
lb.lbStyle = BS_SOLID;
ob = SelectObject(MemDc,CreateBrushIndirect(&lb));
oP = SelectObject(MemDc,GetStockObject(NULL_PEN));
Rectangle(MemDc,0,0,rect.right,rect.bottom);
DeleteObject(Se