2013-06-01 27 views
7

Bir TMainMenu gibi TActionMainMenuBar ekran tarzındaki MDI düğmelerini yapmaya çalışıyorum.TActionMainMenuBar, VCL-Stilleri ve MDI düğmeleri (Simge durumuna küçült, kapat vb.) Stil uygulanmamış.

VCL Styles problem

herhangi bir öneriniz? Bu proje için MDI kullanmayı bırakamam.

+0

Aynı "belge" sınıfına sahip olan Frames, geliştirici ve kullanıcı için gereksiz güçlük çekmeden bunu yapmanıza izin verir. –

+0

MDI birden çok örneğini barındıran bir tek ebeveynli penceresinin fikri ile balık yumurtası edildi olabilir – Peter

+0

Sorunu yeniden oluşturmak için örnek bir kod ekleyebilir misiniz? – RRUZ

cevap

11

Tamam, ilk Bu bir Vcl Stilleri hatası değil, bu bir VCL hatasıdır. Vcl Stilleri devre dışı bırakılmış olsa bile bu sorun görünür.

enter image description here

konu başlık düğmeler çizmek için eski DrawFrameControl WINAPI yöntemini kullanır TCustomMDIMenuButton.Paint yönteminde bulunan

enter image description here.

procedure TCustomMDIMenuButton.Paint; 
begin 
    DrawFrameControl(Canvas.Handle, ClientRect, DFC_CAPTION, 
    MouseStyles[MouseInControl] or ButtonStyles[ButtonStyle] or 
    PushStyles[FState = bsDown]); 
end; 

gibi, bir dolambaçlı yoldan kullanarak ve sonra StylesServices kullanarak yeni boya yöntemi uygulayan bu yöntemi yama yapabilirsiniz Geçici çözüm.

Sadece bu birimi projenize ekleyin.

unit PatchMDIButtons; 

interface 

implementation 

uses 
    System.SysUtils, 
    Winapi.Windows, 
    Vcl.Themes, 
    Vcl.Styles, 
    Vcl.ActnMenus; 

type 
    TCustomMDIMenuButtonClass= class(TCustomMDIMenuButton); 

    TJumpOfs = Integer; 
    PPointer = ^Pointer; 

    PXRedirCode = ^TXRedirCode; 
    TXRedirCode = packed record 
    Jump: Byte; 
    Offset: TJumpOfs; 
    end; 

    PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp; 
    TAbsoluteIndirectJmp = packed record 
    OpCode: Word; 
    Addr: PPointer; 
    end; 

var 
    PaintMethodBackup : TXRedirCode; 

function GetActualAddr(Proc: Pointer): Pointer; 
begin 
    if Proc <> nil then 
    begin 
    if (Win32Platform = VER_PLATFORM_WIN32_NT) and (PAbsoluteIndirectJmp(Proc).OpCode = $25FF) then 
     Result := PAbsoluteIndirectJmp(Proc).Addr^ 
    else 
     Result := Proc; 
    end 
    else 
    Result := nil; 
end; 

procedure HookProc(Proc, Dest: Pointer; var BackupCode: TXRedirCode); 
var 
    n: NativeUInt; 
    Code: TXRedirCode; 
begin 
    Proc := GetActualAddr(Proc); 
    Assert(Proc <> nil); 
    if ReadProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n) then 
    begin 
    Code.Jump := $E9; 
    Code.Offset := PAnsiChar(Dest) - PAnsiChar(Proc) - SizeOf(Code); 
    WriteProcessMemory(GetCurrentProcess, Proc, @Code, SizeOf(Code), n); 
    end; 
end; 

procedure UnhookProc(Proc: Pointer; var BackupCode: TXRedirCode); 
var 
    n: NativeUInt; 
begin 
    if (BackupCode.Jump <> 0) and (Proc <> nil) then 
    begin 
    Proc := GetActualAddr(Proc); 
    Assert(Proc <> nil); 
    WriteProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n); 
    BackupCode.Jump := 0; 
    end; 
end; 


procedure PaintPatch(Self: TObject); 
const 
    ButtonStyles: array[TMDIButtonStyle] of TThemedWindow = (twMDIMinButtonNormal, twMDIRestoreButtonNormal, twMDICloseButtonNormal); 
var 
    LButton : TCustomMDIMenuButtonClass; 
    LDetails: TThemedElementDetails; 
begin 
    LButton:=TCustomMDIMenuButtonClass(Self); 
    LDetails := StyleServices.GetElementDetails(ButtonStyles[LButton.ButtonStyle]); 
    StyleServices.DrawElement(LButton.Canvas.Handle, LDetails, LButton.ClientRect); 
end; 

procedure HookPaint; 
begin 
    HookProc(@TCustomMDIMenuButtonClass.Paint, @PaintPatch, PaintMethodBackup); 
end; 

procedure UnHookPaint; 
begin 
    UnhookProc(@TCustomMDIMenuButtonClass.Paint, PaintMethodBackup); 
end; 


initialization 
HookPaint; 
finalization 
UnHookPaint; 
end. 

sonuç olacaktır

enter image description here enter image description here

Hep VCL stillerini kullanmayı bırakın .......
+0

Harika! Çok teşekkür ederim Rodrigo. –

+0

Hoşgeldiniz, bu konuyu QC sitesine bildirmeyi unutmayın. Http://qc.embarcadero.com/wc/qcmain.aspx – RRUZ

+0

Çok teşekkür ederim! – gabr