mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
249 lines
7.2 KiB
ObjectPascal
249 lines
7.2 KiB
ObjectPascal
{
|
|
Copyright © Norstedts Juridik AB
|
|
Made by Per-Erik Andersson, inspired by J Hamblin - Qtools Software.
|
|
Author grants unrestricted use of this software code.
|
|
All use is on your own risk.
|
|
|
|
J Hamblin has made a component TjhALTBugFix to solve a problem in Vista.
|
|
It can be downloaded from CodeGear Quality centre here:
|
|
http://qc.codegear.com/wc/qcmain.aspx?d=37403
|
|
Below is the text J Hamblin wrote that describes the problem:
|
|
|
|
** Quote **************
|
|
There seems to be a problem with THEMES support in Delphi, in which
|
|
TButton, TCheckBox, TRadioButton and TStaticText standard controls
|
|
vanish in VISTA when the ALT key is pressed. (only TStaticText vanishes in XP).
|
|
If the OS is set to default, pressing the ALT key in XP and Vista has the
|
|
behavior of displaying the underline under the accelerator keys.
|
|
|
|
The mentioned controls vanish the first time ALT is pressed. They can be
|
|
restored by repainting the control in code. Once restored, they are not
|
|
affected by subsequent ALT key presses -- unless a pagecontrol on the form
|
|
changes to a new tabsheet, then all affected controls, both on the tabsheet
|
|
and on the form, will vanish on next ALT press. Due to the pagecontrol issue
|
|
there is no way to set a flag to do the repaint op only once. In MDI applications,
|
|
an ALT key press has the same affect on all child forms at the same time.
|
|
** End quote **************
|
|
|
|
The TjhALTBugFix needs to be put on each form in the application which
|
|
is a problem in many large applications. Therefore I made this component
|
|
that can be dropped on the main form and then handles all delphi forms
|
|
that are created.
|
|
|
|
The component works like this: In Idle it goes through the list of existing
|
|
Delphi forms in TScreen. When a new form is found, its WindowProc is replaced
|
|
with a hook that listens for the event WM_UPDATEUISTATE which is the
|
|
message triggering the error.
|
|
When a form has got an WM_UPDATEUISTATE it gets a flag the says it needs to
|
|
be redrawn. The next time the application enters Idle a repaint is made,
|
|
depending on the property RepaintAll. If it is true all TWinControls on the
|
|
form gets a repaint. If its false only the component that probably needs a
|
|
repaint is repainted (that code mady by J Hamblin).
|
|
The "repaint all" is an precausion for third part components that might behave in
|
|
the same way. RepaintAll is default true.
|
|
Note that this component is only active in Vista. If you want it to
|
|
handle the TStaticText in XP you have to remove the VistaWithTheme check
|
|
in TVistaAltFix.Create.
|
|
|
|
Usage:
|
|
If you want to use this as an component you have to install it into the Delphi IDE.
|
|
If you don't want to do that just add this code in your main form OnCreate:
|
|
|
|
procedure TMainForm.FormCreate(Sender: TObject);
|
|
begin
|
|
TVistaAltFix.Create(Self);
|
|
end;
|
|
|
|
}
|
|
|
|
unit VistaAltFixUnit;
|
|
|
|
interface
|
|
uses
|
|
ExtCtrls, Classes, Contnrs, AppEvnts;
|
|
|
|
type
|
|
TVistaAltFix = class(TComponent)
|
|
private
|
|
FList: TObjectList;
|
|
FApplicationEvents: TApplicationEvents;
|
|
FRepaintAll: Boolean;
|
|
procedure ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
|
|
function VistaWithTheme: Boolean;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
published
|
|
property RepaintAll: Boolean read FRepaintAll write FRepaintAll default True;
|
|
end;
|
|
|
|
procedure Register;
|
|
|
|
implementation
|
|
uses
|
|
Forms, Windows, Messages, Buttons, ComCtrls, Controls, StdCtrls, Themes;
|
|
|
|
type
|
|
TFormObj = class(TObject)
|
|
private
|
|
procedure WndProc(var Message: TMessage);
|
|
public
|
|
Form: TForm;
|
|
OrgProc: TWndMethod;
|
|
Used: Boolean;
|
|
NeedRepaint: Boolean;
|
|
RepaintAll: Boolean;
|
|
constructor Create(aForm: TForm; aRepaintAll: Boolean);
|
|
procedure DoRepaint;
|
|
end;
|
|
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents('MEP', [TVistaAltFix]);
|
|
end;
|
|
|
|
{ TVistaAltFix }
|
|
|
|
procedure TVistaAltFix.ApplicationEventsIdle(Sender: TObject;
|
|
var Done: Boolean);
|
|
var
|
|
I: Integer;
|
|
J: Integer;
|
|
TestForm: TForm;
|
|
begin
|
|
// Initialize
|
|
for I := 0 to FList.Count - 1 do
|
|
TFormObj(FList[i]).Used := False;
|
|
|
|
// Check for new forms
|
|
for I := 0 to Screen.FormCount - 1 do
|
|
begin
|
|
TestForm := Screen.Forms[i];
|
|
for J := 0 to FList.Count - 1 do
|
|
begin
|
|
if TFormObj(FList[J]).Form = TestForm then
|
|
begin
|
|
TFormObj(FList[J]).Used := True;
|
|
TestForm := nil;
|
|
Break;
|
|
end;
|
|
end;
|
|
if Assigned(TestForm) then
|
|
FList.Add(TFormObj.Create(TestForm, RepaintAll));
|
|
end;
|
|
|
|
// Remove destroyed forms, repaint others if needed.
|
|
for I := FList.Count - 1 downto 0 do
|
|
begin
|
|
if not TFormObj(FList[i]).Used then
|
|
FList.Delete(i)
|
|
else
|
|
TFormObj(FList[i]).DoRepaint;
|
|
end;
|
|
end;
|
|
|
|
constructor TVistaAltFix.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
FRepaintAll := True;
|
|
if VistaWithTheme and not (csDesigning in ComponentState) then
|
|
begin
|
|
FList := TObjectList.Create;
|
|
FApplicationEvents := TApplicationEvents.Create(nil);
|
|
FApplicationEvents.OnIdle := ApplicationEventsIdle;
|
|
end;
|
|
end;
|
|
|
|
destructor TVistaAltFix.Destroy;
|
|
begin
|
|
FApplicationEvents.Free;
|
|
FList.Free;
|
|
inherited;
|
|
end;
|
|
|
|
function TVistaAltFix.VistaWithTheme: Boolean;
|
|
var
|
|
OSVersionInfo: TOSVersionInfo;
|
|
begin
|
|
OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
|
|
if GetVersionEx(OSVersionInfo) and
|
|
(OSVersionInfo.dwMajorVersion >= 6) and
|
|
ThemeServices.ThemesEnabled then
|
|
Result := True
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
{ TFormObj }
|
|
|
|
constructor TFormObj.Create(aForm: TForm; aRepaintAll: Boolean);
|
|
begin
|
|
inherited Create;
|
|
Form := aForm;
|
|
RepaintAll := aRepaintAll;
|
|
Used := True;
|
|
OrgProc := Form.WindowProc;
|
|
Form.WindowProc := WndProc;
|
|
end;
|
|
|
|
procedure TFormObj.DoRepaint;
|
|
procedure RepaintBtnControls(TheCtrl: TControl);
|
|
// This method made by J Hamblin - Qtools Software.
|
|
var
|
|
i: integer;
|
|
begin
|
|
if not (TheCtrl is TWinControl) or (TheCtrl is TBitBtn) then
|
|
exit;
|
|
|
|
// repaint only controls of affected type
|
|
if (TheCtrl is TButtonControl) or (TheCtrl is TStaticText) then
|
|
begin
|
|
TWinControl(TheCtrl).Repaint;
|
|
exit; // TButtonControls, TStaticText do not contain controls so skip rest
|
|
end;
|
|
|
|
//
|
|
|
|
for i := 0 to TWinControl(TheCtrl).ControlCount - 1 do
|
|
begin
|
|
// only paint controls on active tabsheet of page control
|
|
if (TheCtrl is TTabSheet) and
|
|
(TTabSheet(TheCtrl).PageIndex <> TTabSheet(TheCtrl).PageControl.ActivePageIndex) then
|
|
continue;
|
|
// recurse
|
|
RepaintBtnControls(TWinControl(TheCtrl).Controls[i]);
|
|
end;
|
|
end;
|
|
|
|
procedure DoRepaint(Ctrl: TControl);
|
|
var
|
|
i: integer;
|
|
begin
|
|
if (Ctrl is TWinControl) then
|
|
begin
|
|
TWinControl(Ctrl).Repaint;
|
|
for i := 0 to TWinControl(Ctrl).ControlCount - 1 do
|
|
DoRepaint(TWinControl(Ctrl).Controls[i]);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if NeedRepaint then
|
|
begin
|
|
NeedRepaint := False;
|
|
if RepaintAll then
|
|
DoRepaint(Form)
|
|
else
|
|
RepaintBtnControls(Form);
|
|
end;
|
|
end;
|
|
|
|
procedure TFormObj.WndProc(var Message: TMessage);
|
|
begin
|
|
OrgProc(Message);
|
|
if (Message.Msg = WM_UPDATEUISTATE) then
|
|
NeedRepaint := True;
|
|
end;
|
|
|
|
end.
|
|
|