Ладно, выкладываю то что сделал: поддержка темы 98 и XP (Виста ещё не готова), цвет и размер кнопок зависят от стиля, возможна горячая смена "темы" (не совсем готова), это типо бета (пока ещё не оптимизировал) и пока только для кнопки свернуть (хотя пределать не долго):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, UxTheme, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormResize(Sender: TObject);
procedure PaintB;
procedure LoadTheme;
procedure FormCreate(Sender: TObject);
private
procedure WMNCPAINT(var Msg: TMessage); message WM_NCPAINT;
procedure WMNCACTIVATE(var Msg: TWMNCActivate); message WM_NCACTIVATE;
procedure WMTema(var Msg: TMessage); message WM_THEMECHANGED;
public
end;
var
Form1: TForm1;
NonBut, Press, Focus, XpT: Boolean;
Rec: TRect;
Theme: HTHEME;
FMouseHook:THandle;
implementation
procedure TForm1.LoadTheme;
var
RightB: integer;
begin
if InitThemeLibrary and UseThemes then
begin
Theme:=OpenThemeData(Form1.Handle, 'Window');
XpT:=True;
if (biSystemMenu in Form1.BorderIcons) and ((biMinimize in Form1.BorderIcons) or (biMaximize in Form1.BorderIcons)) then
RightB:=3*(GetSystemMetrics(SM_CXSIZE)-2)+6
else
if (biSystemMenu in Form1.BorderIcons) and (biHelp in Form1.BorderIcons) then
RightB:=2*(GetSystemMetrics(SM_CXSIZE)-2)+6
else
if biSystemMenu in Form1.BorderIcons then
RightB:=GetSystemMetrics(SM_CXSIZE)+4
else
RightB:=6;
Rec.Left:=Form1.Width-(RightB+GetSystemMetrics(SM_CXSIZE)-4);
Rec.Top:=6;
Rec.Right:=Form1.Width-RightB;
Rec.Bottom:=GetSystemMetrics(SM_CYSIZE)+2;
end
else
begin
XpT:=False;
if (biSystemMenu in Form1.BorderIcons) and ((biMinimize in Form1.BorderIcons) or (biMaximize in Form1.BorderIcons)) then
RightB:=3*(GetSystemMetrics(SM_CXSIZE)-2)+8
else
if (biSystemMenu in Form1.BorderIcons) and (biHelp in Form1.BorderIcons) then
RightB:=2*(GetSystemMetrics(SM_CXSIZE)-2)+8
else
if biSystemMenu in Form1.BorderIcons then
RightB:=GetSystemMetrics(SM_CXSIZE)+8
else
RightB:=6;
Rec.Left:=Form1.Width-(RightB+GetSystemMetrics(SM_CXSIZE)-2);
Rec.Top:=6;
Rec.Right:=Form1.Width-RightB;
Rec.Bottom:=GetSystemMetrics(SM_CYSIZE)+2;
end;
end;
procedure TForm1.WMTema(var Msg: TMessage);
begin
CloseThemeData(Theme);
LoadTheme;
end;
procedure TForm1.WMNCPAINT(var Msg: TMessage);
begin
inherited;
PaintB;
end;
procedure TForm1.FormResize(Sender: TObject);
var
RightB: integer;
begin
if XpT then
begin
if (biSystemMenu in Form1.BorderIcons) and ((biMinimize in Form1.BorderIcons) or (biMaximize in Form1.BorderIcons)) then
RightB:=3*(GetSystemMetrics(SM_CXSIZE)-2)+6
else
if (biSystemMenu in Form1.BorderIcons) and (biHelp in Form1.BorderIcons) then
RightB:=2*(GetSystemMetrics(SM_CXSIZE)-2)+6
else
if biSystemMenu in Form1.BorderIcons then
RightB:=GetSystemMetrics(SM_CXSIZE)+4
else
RightB:=6;
Rec.Left:=Form1.Width-(RightB+GetSystemMetrics(SM_CXSIZE)-4);
Rec.Top:=6;
Rec.Right:=Form1.Width-RightB;
Rec.Bottom:=GetSystemMetrics(SM_CYSIZE)+2;
end
else
begin
if (biSystemMenu in Form1.BorderIcons) and ((biMinimize in Form1.BorderIcons) or (biMaximize in Form1.BorderIcons)) then
RightB:=3*(GetSystemMetrics(SM_CXSIZE)-2)+8
else
if (biSystemMenu in Form1.BorderIcons) and (biHelp in Form1.BorderIcons) then
RightB:=2*(GetSystemMetrics(SM_CXSIZE)-2)+8
else
if biSystemMenu in Form1.BorderIcons then
RightB:=GetSystemMetrics(SM_CXSIZE)+8
else
RightB:=6;
Rec.Left:=Form1.Width-(RightB+GetSystemMetrics(SM_CXSIZE)-2);
Rec.Top:=6;
Rec.Right:=Form1.Width-RightB;
Rec.Bottom:=GetSystemMetrics(SM_CYSIZE)+2;
end;
end;
procedure TForm1.WMNCACTIVATE(var Msg: TWMNCActivate);
begin
Focus:=Msg.Active;
inherited;
PaintB;
end;
procedure InitMouseLeaveHook;
function MouseHookProc(nCode:Integer;wParam:UINT;lParam:PMsg):LRESULT; stdcall;
begin
Result:=CallNextHookEx(FMouseHook,nCode,wParam,Integer(lParam));
if nCode=HC_ACTION then
case lParam.message of
WM_NCMOUSELEAVE:
begin
Press:=False;
NonBut:=True;
Form1.PaintB;
end;
WM_NCMOUSEMOVE:
begin
Dec(lParam.Pt.X, Form1.Left);
Dec(lParam.Pt.Y, Form1.Top);
if PtInRect(Rec, lParam.Pt) then
begin
if HiWord(GetAsyncKeyState(VK_LBUTTON))<>0 then
begin
Press:=True;
NonBut:=False;
end
else
begin
Press:=False;
NonBut:=False;
end;
end
else
begin
Press:=False;
NonBut:=True;
end;
Form1.PaintB;
end;
WM_NCRBUTTONDOWN:
begin
Dec(lParam.Pt.X, Form1.Left);
Dec(lParam.Pt.Y, Form1.Top);
if PtInRect(Rec, lParam.pt) then
begin
NonBut:=False;
Press:=False;
Form1.PaintB;
lParam.message:=0;
end;
end;
WM_NCLBUTTONDOWN:
begin
Dec(lParam.Pt.X, Form1.Left);
Dec(lParam.Pt.Y, Form1.Top);
if PtInRect(Rec, lParam.pt) then
begin
if not Form1.Focused then
SetForegroundWindow(Form1.Handle);
Press:=True;
NonBut:=False;
Form1.PaintB;
lParam.message:=0;
end
else
begin
Press:=False;
NonBut:=True;
end;
end;
WM_NCLBUTTONUP:
begin
Dec(lParam.Pt.X, Form1.Left);
Dec(lParam.Pt.Y, Form1.Top);
Press:=False;
if PtInRect(Rec, lParam.Pt) then
begin
NonBut:=False;
Form1.PaintB
end
else
NonBut:=True;
end;
end;
end;
begin
if FMouseHook=0 then FMouseHook:=SetWindowsHookEx(WH_GETMESSAGE,@MouseHookProc,0,GetCurrentThreadId);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
InitMouseLeaveHook;
LoadTheme;
NonBut:=True;
end;
procedure TForm1.PaintB;
var
DC: HDC;
begin
DC:=GetWindowDC(Form1.Handle);
if NonBut and Focus then
begin
if XpT then
DrawThemeBackground(Theme, DC, WP_MINBUTTON, MINBS_NORMAL, Rec, nil)
else
DrawFrameControl(DC, rec, DFC_CAPTION, DFCS_CAPTIONMIN);
ReleaseDC(Form1.Handle, DC);
exit;
end;
if (not Press) and (not NonBut) and Focus then
begin
if XpT then
DrawThemeBackground(Theme, DC, WP_MINBUTTON, MINBS_HOT, Rec, nil)
else
DrawFrameControl(DC, rec, DFC_CAPTION, DFCS_CAPTIONMIN);
ReleaseDC(Form1.Handle, DC);
exit;
end;
if Press and (not NonBut) and Focus then
begin
if XpT then
DrawThemeBackground(Theme, DC, WP_MINBUTTON, MINBS_PUSHED, Rec, nil)
else
DrawFrameControl(DC, rec, DFC_CAPTION, DFCS_CAPTIONMIN or DFCS_PUSHED);
ReleaseDC(Form1.Handle, DC);
exit;
end;
if NonBut and (not Focus) then
begin
if XpT then
DrawThemeBackground(Theme, DC, WP_MINBUTTON, 5 , Rec, nil)
else
DrawFrameControl(DC, rec, DFC_CAPTION, DFCS_CAPTIONMIN);
ReleaseDC(Form1.Handle, DC);
exit;
end;
if (not NonBut) and (not Focus) then
begin
if XpT then
DrawThemeBackground(Theme, DC, WP_MINBUTTON, MINBS_HOT, Rec, nil)
else
DrawFrameControl(DC, rec, DFC_CAPTION, DFCS_CAPTIONMIN);
ReleaseDC(Form1.Handle, DC);
exit;
end;
if XpT then
DrawThemeBackground(Theme, DC, WP_MINBUTTON, MINBS_NORMAL, Rec, nil)
else
DrawFrameControl(DC, rec, DFC_CAPTION, DFCS_CAPTIONMIN);
ReleaseDC(Form1.Handle, DC);
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
UnhookWindowsHookEx(FMouseHook);
if XpT then CloseThemeData(Theme);
end;
end.
Жду полезной критики, ибо помощь мне не помешает (а то сейчас занит другим) :) |