?? anibtn.pas
字號:
unit AniBtn;
interface
uses Windows, Messages, CommCtrl;
const
// 動畫按鈕控件類名
WC_ANIBTN = 'AniBtn';
// 控件自定消息 ~~
// 注意, 只有將消息定義在這個范圍, 才不會沖突
ABM_FIRSTMSG = (WM_APP + 0);
// Purpose: 設置動畫定時器延時
// wParam: Integer - 新的定時器延時(毫秒為單位)
// lParam: 略
// Return: 略
ABM_SETTIMER = (ABM_FIRSTMSG + 0);
// Purpose: 取得動畫定時器延時
// wParam: 略
// lParam: 略
// Return: Integer - 當前定時器延時(毫秒為單位)
ABM_GETTIMER = (ABM_FIRSTMSG + 1);
// Purpose: 設置動畫圖像列表
// wParam: HIMAGELIST - 圖像列表控件句柄
// lParam: 略
// Return: 略
ABM_SETIMAGELIST = (ABM_FIRSTMSG + 2);
// Purpose: 取得動畫圖像列表
// wParam: 略
// lParam: 略
// Return: HIMAGELIST - 當前圖像列表句柄
ABM_GETIMAGELIST = (ABM_FIRSTMSG + 3);
// 對控件消息的簡單包裝
procedure AniBtn_SetTimer(hWnd: HWND; nTimeOut: Integer);
function AniBtn_GetTimer(hWnd: HWND): Integer;
procedure AniBtn_SetImageList(hWnd: HWND; himl: HIMAGELIST);
function AniBtn_GetImageList(hWnd: HWND): HIMAGELIST;
// 注冊or反注冊控件
function AniBtn_RegisterClass(HInst: THandle; fGlobalClass: BOOL): ATOM; stdcall;
function AniBtn_UnregisterClass(HInst: THandle): BOOL; stdcall;
implementation
uses SuperCls;
// 設置定時器間隔
procedure AniBtn_SetTimer(hWnd: HWND; nTimeOut: Integer);
begin
SendMessage(hWnd, ABM_SETTIMER, nTimeout, 0);
end;
// 取得定時器間隔
function AniBtn_GetTimer(hWnd: HWND): Integer;
begin
Result := SendMessage(hWnd, ABM_GETTIMER, 0, 0);
end;
// 設置動畫圖像列表
procedure AniBtn_SetImageList(hWnd: HWND; himl: HIMAGELIST);
begin
SendMessage(hWnd, ABM_SETIMAGELIST, himl, 0);
end;
// 取得動畫圖像列表
function AniBtn_GetImageList(hWnd: HWND): HIMAGELIST;
begin
Result := SendMessage(hWnd, ABM_GETIMAGELIST, 0, 0);
end;
type
// 按鈕額外空間結構
P_AniBtn_WndExtraBytes = ^T_AniBtn_WndExtraBytes;
T_AniBtn_WndExtraBytes = packed record
himl: HIMAGELIST; // 圖像列表控件句柄
iImage: Integer; // 下一個要顯示的圖片
nTimeout: Integer; // 圖片變化時間間隔
end;
// 按鈕ABM_SETTIMER處理
procedure AniBtn_OnSetTimer(hWnd: HWND; nTimeout: Integer); stdcall;
begin
SuperCls_SetWindowLong(hWnd, Integer(@P_AniBtn_WndExtraBytes(0).nTimeout), nTimeout);
SetTimer(hWnd, 1, nTimeout, nil);
end;
// 按鈕ABM_GETTIMER處理
function AniBtn_OnGetTimer(hWnd: HWND): Integer; stdcall;
begin
Result := SuperCls_GetWindowLong(hWnd, Integer(@P_AniBtn_WndExtraBytes(0).nTimeout));
end;
// 按鈕ABM_SETIMAGELIST處理
procedure AniBtn_OnSetImageList(hWnd: HWND; himl: HIMAGELIST); stdcall;
begin
SuperCls_SetWindowLong(hWnd, Integer(@P_AniBtn_WndExtraBytes(0).himl), himl);
SuperCls_SetWindowLong(hWnd, Integer(@P_AniBtn_WndExtraBytes(0).iImage), 0);
end;
// 按鈕ABM_GETIMAGELIST處理
function AniBtn_OnGetImageList(hWnd: HWND): HIMAGELIST; stdcall;
begin
Result := SuperCls_GetWindowLong(hWnd, Integer(@P_AniBtn_WndExtraBytes(0).himl));
end;
// 調用基類(Button)窗口過程
function AniBtn_CallBaseClass(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
Result := CallWindowProc(SuperCls_GetWndProcBaseCls(hWnd), hWnd, uMsg, wParam, lParam);
end;
// 按鈕WM_CREATE處理
function AniBtn_OnCreate(hWnd: HWND; lpCreateStruct: PCreateStruct): BOOL;
begin
// 缺省延時為0.25秒
AniBtn_SetTimer(hWnd, 250);
// 調用基類處理過程
Result := AniBtn_CallBaseClass(hWnd, WM_CREATE, 0, Integer(lpCreateStruct)) <> -1;
end;
// 按鈕WM_DESTROY處理
procedure AniBtn_OnDestroy(hWnd: HWND);
var
himl: HIMAGELIST;
begin
// 清除關聯的圖像列表
himl := AniBtn_GetImageList(hWnd);
if (himl <> 0) then ImageList_Destroy(himl);
// 刪除動畫定時器
KillTimer(hWnd, 1);
// 調用基類處理過程
AniBtn_CallBaseClass(hWnd, WM_DESTROY, 0, 0);
end;
// 按鈕WM_TIMER處理
procedure AniBtn_OnTimer(hWnd: HWND; id: UINT);
var
himl: HIMAGELIST;
iImage: Integer;
hiconOld: HICON;
begin
himl := AniBtn_GetImageList(hWnd);
if (himl <> 0) then
begin
// 要顯示的圖像
iImage := SuperCls_GetWindowLong(hWnd, Integer(@P_AniBtn_WndExtraBytes(0).iImage));
// 修改按鈕圖標
hiconOld := SendMessage(hWnd, BM_SETIMAGE, IMAGE_ICON, ImageList_GetIcon(himl, iImage, ILD_NORMAL));
// 清除老的圖標
if (hiconOld <> 0) then DestroyIcon(hiconOld);
// 后繼圖像編號
iImage := (iImage + 1) mod ImageList_GetImageCount(himl);
SuperCls_SetWindowLong(hWnd, Integer(@P_AniBtn_WndExtraBytes(0).iImage), iImage);
end;
end;
// 按鈕消息處理回調
function AniBtn_WndProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
Result := 0;
case (uMsg) of
// 標準窗口消息
WM_CREATE:
begin
if AniBtn_OnCreate(hWnd, PCreateStruct(lParam)) = FALSE then Result := -1;
end;
WM_DESTROY:
begin
AniBtn_OnDestroy(hWnd);
end;
WM_TIMER:
begin
AniBtn_OnTimer(hWnd, wParam);
end;
// 控件自定消息
ABM_SETTIMER:
begin
AniBtn_OnSetTimer(hWnd, wParam);
end;
ABM_GETTIMER:
begin
Result := AniBtn_OnGetTimer(hWnd);
end;
ABM_SETIMAGELIST:
begin
AniBtn_OnSetImageList(hWnd, wParam);
end;
ABM_GETIMAGELIST:
begin
Result := AniBtn_OnGetImageList(hWnd);
end;
else Result := AniBtn_CallBaseClass(hWnd, uMsg, wParam, lParam);
end;
end;
// 注冊動畫按鈕類
function AniBtn_RegisterClass(HInst: THandle; fGlobalClass: BOOL): ATOM; stdcall;
var
wc: TWndClassEx;
begin
ZeroMemory(@wc, SizeOf(TWndClassEx));
wc.cbSize := SizeOf(TWndClassEx);
// 取基類(Button)信息
if (GetClassInfoEx(0, 'BUTTON', wc) = FALSE) then
begin
Result := INVALID_ATOM;
Exit;
end;
// InitCommonControls()其實是comctl32.dll中的一個空函數,
// 一般調用它是為了保證在程序啟動時自動載入comctl32.dll,
// 而該DLL在載入的時候, 會自動注冊其所包含控件的窗口類,
// 隨后, 即可直接根據類名來建立控件了.. :~)
// 這里有兩點理由可以不調用InitCommonControls()函數,
// 1.程序已經靜態調用了comctl32.dll中的ImageList_Create()
// 來建立圖像列表, 所以comctl32.dll同樣會自動載入..
// 2.圖像列表并沒有對應的窗口類, 無須注冊, 也可以正常使用
// InitCommonControls();
// 設置我們的類名
wc.lpszClassName := WC_ANIBTN;
// 欲注冊類的模塊
wc.hInstance := HInst;
// 要求注冊全局類
if (fGlobalClass) then wc.style := wc.style or CS_GLOBALCLASS;
// 注冊superclass
Result := SuperCls_RegisterClassEx(@wc, @AniBtn_WndProc, 0, SizeOf(T_AniBtn_WndExtraBytes));
end;
// 注銷動畫按鈕類
function AniBtn_UnregisterClass(HInst: THandle): BOOL; stdcall;
begin
Result := UnregisterClass(WC_ANIBTN, HInst);
end;
end.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -