2013-06-01 19 views
7

Ich versuche TActionMainMenuBar gestylte MDI-Schaltflächen wie ein TMainMenu anzuzeigen.TActionMainMenuBar, VCL-Styles und MDI-Schaltflächen (Minimieren, Schließen usw.) werden nicht formatiert.

VCL Styles problem

Irgendwelche Vorschläge? Ich kann nicht aufhören, MDI für dieses Projekt zu verwenden.

+0

Sie immer VCL Arten stoppen konnte mit ....... –

+0

MDI wurde mit der Idee eines einzigen übergeordneten Fenster Hosting mehrere Instanzen gelaicht von der gleichen Klasse von "Dokument", Rahmen können Sie genau das tun, ohne den unnötigen Aufwand für den Entwickler und den Benutzer. – Peter

+0

Können Sie einen Beispielcode einfügen, um das Problem zu reproduzieren? – RRUZ

Antwort

11

Ok, erste dies ist kein Vcl Styles Fehler, ist dies ein VCL Fehler. Dieses Problem tritt auf, selbst wenn die Vcl-Stile deaktiviert sind.

enter image description here

enter image description here

Das Problem in dem TCustomMDIMenuButton.Paint Verfahren befindet, die die alte DrawFrameControl winapi Methode verwendet die Beschriftung Tasten zu zeichnen.

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

Wie umgehen Sie diese Methode Patch kann einen Umweg und anschließend eine neue Farbe Methode, um die StylesServices mit der Umsetzung.

Fügen Sie dieses Gerät zu Ihrem Projekt hinzu.

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. 

Das Ergebnis wird

enter image description here sein enter image description here

+0

Großartig! Vielen Dank Rodrigo. –

+0

Sie sind willkommen, don 'vergessen Sie, dieses Problem auf der QC-Website http://qc.embarcadero.com/wc/qcmain.aspx – RRUZ

+0

Vielen Dank! – gabr