284 lines
7.9 KiB
Plaintext
284 lines
7.9 KiB
Plaintext
unit fBase508Form;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
|
Dialogs, StdCtrls, ExtCtrls, VA508AccessibilityManager, OR2006Compatibility, uConst;
|
|
|
|
type
|
|
TAccessibilityAction = (aaColorConversion, aaTitleBarHeightAdjustment,
|
|
aaFixTabStopArrowNavigationBug);
|
|
TAccessibilityActions = set of TAccessibilityAction;
|
|
|
|
TfrmBase508Form = class(Tfrm2006Compatibility)
|
|
amgrMain: TVA508AccessibilityManager;
|
|
procedure FormKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
private
|
|
FLoadedCalled: boolean;
|
|
FDefaultButton: TButton;
|
|
FActions: TAccessibilityActions;
|
|
FUnfocusableControlPtr: TMethod;
|
|
procedure AdjustForTitleBarHeightChanges;
|
|
function GetDefaultButton(OwnerComponent: TComponent) : TButton;
|
|
procedure ClickDefaultButton;
|
|
procedure SetDefaultButton(const Value: TButton);
|
|
procedure ModifyUnfocusableControl(Control: TWinControl; Attach: boolean);
|
|
procedure UM508(var Message: TMessage); message UM_508;
|
|
protected
|
|
procedure Activate; override;
|
|
procedure Loaded; override;
|
|
procedure SetParent(AParent: TWinControl); override;
|
|
procedure Notification(AComponent: TComponent;
|
|
Operation: TOperation); override;
|
|
procedure UpdateAccessabilityActions(var Actions: TAccessibilityActions); virtual;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
property DefaultButton : TButton read FDefaultButton write SetDefaultButton;
|
|
end;
|
|
|
|
var
|
|
Last508KeyCode: LongInt = 0;
|
|
|
|
procedure UnfocusableControlEnter(Self, Sender: TObject);
|
|
|
|
implementation
|
|
|
|
uses ORFn, VA508AccessibilityRouter, VAUtils;
|
|
|
|
{$R *.dfm}
|
|
|
|
const
|
|
MSG_508_CODE_TITLE_BAR = 1;
|
|
|
|
type
|
|
TFriendWinControl = class(TWinControl);
|
|
|
|
procedure UnfocusableControlEnter(Self, Sender: TObject);
|
|
var
|
|
ctrl: TWinControl;
|
|
begin
|
|
if (Last508KeyCode = VK_UP) or (Last508KeyCode = VK_LEFT) then
|
|
begin
|
|
ctrl := TWinControl(Sender);
|
|
ctrl := TFriendWinControl(ctrl.Parent).FindNextControl(ctrl, FALSE, TRUE, FALSE);
|
|
if assigned(ctrl) and (ctrl <> Sender) then
|
|
ctrl.SetFocus;
|
|
Last508KeyCode := 0;
|
|
end
|
|
else
|
|
if (Last508KeyCode = VK_DOWN) or (Last508KeyCode = VK_RIGHT) then
|
|
begin
|
|
keybd_event(VK_TAB,0,0,0);
|
|
keybd_event(VK_TAB,0,KEYEVENTF_KEYUP,0);
|
|
Last508KeyCode := 0;
|
|
end;
|
|
end;
|
|
|
|
{ TfrmBase508Form }
|
|
|
|
// All forms in CPRS should be a descendant of this form, even those that are programatically
|
|
// made children of other forms.
|
|
procedure TfrmBase508Form.Activate;
|
|
begin
|
|
Last508KeyCode := 0;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TfrmBase508Form.AdjustForTitleBarHeightChanges;
|
|
var
|
|
OldResize: TNotifyEvent;
|
|
begin
|
|
if parent <> nil then exit;
|
|
OldResize := OnResize;
|
|
try
|
|
OnResize := nil;
|
|
AdjustForWindowsXPStyleTitleBar(Self);
|
|
finally
|
|
OnResize := OldResize;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmBase508Form.FormKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
begin
|
|
if (Key = VK_RETURN) and (ssCtrl in Shift) then begin
|
|
ClickDefaultButton;
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmBase508Form.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if FLoadedCalled and (aaFixTabStopArrowNavigationBug in FActions) and (AComponent is TWinControl) then
|
|
begin
|
|
ModifyUnfocusableControl(TWinControl(AComponent), Operation = opInsert);
|
|
end;
|
|
end;
|
|
|
|
function TfrmBase508Form.GetDefaultButton(ownerComponent: TComponent): TButton;
|
|
var
|
|
i : integer;
|
|
begin
|
|
Result := nil;
|
|
with ownerComponent do begin
|
|
for i := 0 to ComponentCount - 1 do begin
|
|
if Components[i] is TButton then begin
|
|
if TButton(Components[i]).Default then
|
|
Result := TButton(Components[i]);
|
|
end
|
|
else if Components[i] is TFrame then
|
|
Result := GetDefaultButton(Components[i]);
|
|
if Assigned(Result) then
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmBase508Form.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
FLoadedCalled := TRUE;
|
|
end;
|
|
|
|
procedure TfrmBase508Form.ModifyUnfocusableControl(Control: TWinControl; Attach: boolean);
|
|
var
|
|
wc: TFriendWinControl;
|
|
begin
|
|
if (Control is TPanel) or (Control is TCustomGroupBox) then
|
|
begin
|
|
wc := TFriendWinControl(Control);
|
|
if not wc.TabStop then
|
|
begin
|
|
if not assigned(wc.OnEnter) then
|
|
begin
|
|
if Attach then
|
|
wc.OnEnter := TNotifyEvent(FUnfocusableControlPtr);
|
|
end
|
|
else
|
|
begin
|
|
if (not Attach) and (TMethod(wc.OnEnter).Code = FUnfocusableControlPtr.Code) then
|
|
wc.OnEnter := nil;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmBase508Form.SetDefaultButton(const Value: TButton);
|
|
begin
|
|
FDefaultButton := Value;
|
|
end;
|
|
|
|
procedure TfrmBase508Form.SetParent(AParent: TWinControl);
|
|
begin
|
|
inherited SetParent(AParent);
|
|
if assigned(AParent) then
|
|
AutoScroll := False;
|
|
end;
|
|
|
|
// to prevent a 508 feature from taking place, remove that feature's flag form the Actions set
|
|
// in an override of the UpdateAccessabilityActions proc.
|
|
procedure TfrmBase508Form.UM508(var Message: TMessage);
|
|
begin
|
|
case Message.WParam of
|
|
MSG_508_CODE_TITLE_BAR: AdjustForTitleBarHeightChanges;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmBase508Form.UpdateAccessabilityActions(var Actions: TAccessibilityActions);
|
|
begin
|
|
end;
|
|
|
|
type
|
|
TExposedBtn = class(TButton);
|
|
|
|
procedure TfrmBase508Form.ClickDefaultButton;
|
|
var
|
|
tempDefaultBtn: TButton;
|
|
begin
|
|
if Assigned(DefaultButton) then
|
|
tempDefaultBtn := DefaultButton
|
|
else
|
|
tempDefaultBtn := GetDefaultButton(Self);
|
|
if Assigned(tempDefaultBtn) then
|
|
if tempDefaultBtn.Visible then
|
|
TExposedBtn(tempDefaultBtn).Click;
|
|
end;
|
|
|
|
constructor TfrmBase508Form.Create(AOwner: TComponent);
|
|
|
|
procedure AdjustControls(Control: TWinControl);
|
|
var
|
|
i: integer;
|
|
wc: TWinControl;
|
|
begin
|
|
for I := 0 to Control.ControlCount-1 do
|
|
begin
|
|
if Control.Controls[i] is TWinControl then
|
|
begin
|
|
wc := TWinControl(Control.Controls[i]);
|
|
if not wc.TabStop then
|
|
ModifyUnfocusableControl(wc, TRUE);
|
|
AdjustControls(wc);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
inherited Create(AOwner);
|
|
if not assigned(Parent) then
|
|
AutoScroll := True;
|
|
FActions := [aaColorConversion, aaTitleBarHeightAdjustment, aaFixTabStopArrowNavigationBug];
|
|
UpdateAccessabilityActions(FActions);
|
|
if aaColorConversion in FActions then
|
|
UpdateColorsFor508Compliance(Self);
|
|
|
|
if aaTitleBarHeightAdjustment in FActions then
|
|
PostMessage(Handle, UM_508, MSG_508_CODE_TITLE_BAR, 0);
|
|
|
|
if aaFixTabStopArrowNavigationBug in FActions then
|
|
begin
|
|
FUnfocusableControlPtr.Code := @UnfocusableControlEnter;
|
|
FUnfocusableControlPtr.Data := nil;
|
|
AdjustControls(Self);
|
|
end;
|
|
Last508KeyCode := 0;
|
|
end;
|
|
|
|
const
|
|
KEY_MASK = $20000000; // ignore Alt keys
|
|
var
|
|
KeyMonitorHook: HHOOK;
|
|
MouseMonitorHook: HHOOK;
|
|
|
|
function KeyMonitorProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; StdCall;
|
|
begin
|
|
if (code = HC_ACTION) and ((lParam and KEY_MASK) = 0) then
|
|
Last508KeyCode := wParam;
|
|
Result := CallNextHookEx(KeyMonitorHook, Code, wParam, lParam);
|
|
end;
|
|
|
|
// if mouse click clear last key code
|
|
function MouseMonitorProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; StdCall;
|
|
begin
|
|
if (Code = HC_ACTION) and (wParam > WM_MOUSEFIRST) and (wParam <= WM_MOUSELAST) then
|
|
Last508KeyCode := 0;
|
|
Result := CallNextHookEx(MouseMonitorHook, Code, wParam, lParam);
|
|
end;
|
|
|
|
initialization
|
|
KeyMonitorHook := SetWindowsHookEx(WH_KEYBOARD, KeyMonitorProc, 0, GetCurrentThreadID);
|
|
MouseMonitorHook := SetWindowsHookEx(WH_MOUSE, MouseMonitorProc, 0, GetCurrentThreadID);
|
|
|
|
SpecifyFormIsNotADialog(TfrmBase508Form);
|
|
SpecifyFormIsNotADialog(Tfrm2006Compatibility);
|
|
|
|
finalization
|
|
UnhookWindowsHookEx(KeyMonitorHook);
|
|
UnhookWindowsHookEx(MouseMonitorHook);
|
|
|
|
end.
|