| 1 | unit fVA508HiddenJawsMainWindow; | 
|---|
| 2 |  | 
|---|
| 3 | interface | 
|---|
| 4 |  | 
|---|
| 5 | uses | 
|---|
| 6 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, | 
|---|
| 7 | Dialogs, Contnrs, ExtCtrls, ComObj, VA508AccessibilityConst, AppEvnts; | 
|---|
| 8 |  | 
|---|
| 9 | type | 
|---|
| 10 | TfrmVA508HiddenJawsMainWindow = class(TForm) | 
|---|
| 11 | ReloadTimer: TTimer; | 
|---|
| 12 | CloseINIFilesTimer: TTimer; | 
|---|
| 13 | procedure FormCreate(Sender: TObject); | 
|---|
| 14 | procedure FormDestroy(Sender: TObject); | 
|---|
| 15 | procedure ReloadTimerTimer(Sender: TObject); | 
|---|
| 16 | procedure CloseINIFilesTimerTimer(Sender: TObject); | 
|---|
| 17 | private | 
|---|
| 18 | FRootCaption: string; | 
|---|
| 19 | FPostWindow: HWnd; | 
|---|
| 20 | FCloseFilesEvent: TNotifyEvent; | 
|---|
| 21 | FData: string; | 
|---|
| 22 | FVariables: string; | 
|---|
| 23 | FDataWindowPool: TList; | 
|---|
| 24 | FDataWindows: TObjectList; | 
|---|
| 25 | FComponentDataCallBackProc: TComponentDataRequestProc; | 
|---|
| 26 | FConfigChangePending: boolean; | 
|---|
| 27 | FConfigReloadProc: TConfigReloadProc; | 
|---|
| 28 | procedure ConverAccelChars(var text: string); | 
|---|
| 29 | protected | 
|---|
| 30 | procedure WndProc(var Msg: TMessage); override; | 
|---|
| 31 | public | 
|---|
| 32 | procedure ConfigReloadNeeded; | 
|---|
| 33 | procedure WriteData(VarName, Value: string); | 
|---|
| 34 | procedure PostData; | 
|---|
| 35 | procedure ResetINITimer(Event: TNotifyEvent); | 
|---|
| 36 | property ConfigReloadProc: TConfigReloadProc read FConfigReloadProc write FConfigReloadProc; | 
|---|
| 37 | property ComponentDataCallBackProc: TComponentDataRequestProc read FComponentDataCallBackProc write FComponentDataCallBackProc; | 
|---|
| 38 | property ConfigChangePending: boolean read FConfigChangePending write FConfigChangePending; | 
|---|
| 39 | end; | 
|---|
| 40 |  | 
|---|
| 41 | var | 
|---|
| 42 | frmVA508HiddenJawsMainWindow: TfrmVA508HiddenJawsMainWindow; | 
|---|
| 43 |  | 
|---|
| 44 | implementation | 
|---|
| 45 |  | 
|---|
| 46 | uses JAWSCommon, fVA508HiddenJawsDataWindow, VAUtils; | 
|---|
| 47 |  | 
|---|
| 48 | {$R *.dfm} | 
|---|
| 49 |  | 
|---|
| 50 | procedure TfrmVA508HiddenJawsMainWindow.CloseINIFilesTimerTimer( | 
|---|
| 51 | Sender: TObject); | 
|---|
| 52 | begin | 
|---|
| 53 | CloseINIFilesTimer.Enabled := FALSE; | 
|---|
| 54 | if assigned(FCloseFilesEvent) then | 
|---|
| 55 | FCloseFilesEvent(Sender); | 
|---|
| 56 | end; | 
|---|
| 57 |  | 
|---|
| 58 | procedure TfrmVA508HiddenJawsMainWindow.ConfigReloadNeeded; | 
|---|
| 59 | begin | 
|---|
| 60 | ReloadTimer.Enabled := FALSE; | 
|---|
| 61 | ReloadTimer.Enabled := TRUE; | 
|---|
| 62 | FConfigChangePending := TRUE; | 
|---|
| 63 | end; | 
|---|
| 64 |  | 
|---|
| 65 | // MSAA messes up strings with & chars | 
|---|
| 66 | procedure TfrmVA508HiddenJawsMainWindow.ConverAccelChars(var text: string); | 
|---|
| 67 | var | 
|---|
| 68 | i: integer; | 
|---|
| 69 | convert: boolean; | 
|---|
| 70 | begin | 
|---|
| 71 | repeat | 
|---|
| 72 | i := pos('&', text); | 
|---|
| 73 | if i > 0 then | 
|---|
| 74 | begin | 
|---|
| 75 | convert := (i = length(text)); | 
|---|
| 76 | if not convert then | 
|---|
| 77 | convert := not (text[i+1] in ['A'..'Z','a'..'z','0'..'9']); | 
|---|
| 78 | delete(text,i,1); | 
|---|
| 79 | if convert then | 
|---|
| 80 | insert(' and ', text, i); | 
|---|
| 81 | end; | 
|---|
| 82 | until i = 0; | 
|---|
| 83 | end; | 
|---|
| 84 |  | 
|---|
| 85 | procedure TfrmVA508HiddenJawsMainWindow.FormCreate(Sender: TObject); | 
|---|
| 86 | begin | 
|---|
| 87 | ErrorCheckClassName(Self, DLL_MAIN_WINDOW_CLASS); | 
|---|
| 88 | FRootCaption := DLL_WINDOW_TITLE; | 
|---|
| 89 | Caption := FRootCaption; | 
|---|
| 90 | FDataWindowPool := TList.Create; | 
|---|
| 91 | FDataWindows := TObjectList.Create; | 
|---|
| 92 | end; | 
|---|
| 93 |  | 
|---|
| 94 | procedure TfrmVA508HiddenJawsMainWindow.FormDestroy(Sender: TObject); | 
|---|
| 95 | begin | 
|---|
| 96 | FreeAndNil(FDataWindowPool); | 
|---|
| 97 | FreeAndNil(FDataWindows); | 
|---|
| 98 | end; | 
|---|
| 99 |  | 
|---|
| 100 | procedure TfrmVA508HiddenJawsMainWindow.ReloadTimerTimer(Sender: TObject); | 
|---|
| 101 | begin | 
|---|
| 102 | ReloadTimer.Enabled := FALSE; | 
|---|
| 103 | if assigned(FConfigReloadProc) then | 
|---|
| 104 | FConfigReloadProc; | 
|---|
| 105 | FConfigChangePending := FALSE; | 
|---|
| 106 | end; | 
|---|
| 107 |  | 
|---|
| 108 | procedure TfrmVA508HiddenJawsMainWindow.ResetINITimer(Event: TNotifyEvent); | 
|---|
| 109 | begin | 
|---|
| 110 | FCloseFilesEvent := Event; | 
|---|
| 111 | CloseINIFilesTimer.Enabled := FALSE; | 
|---|
| 112 | CloseINIFilesTimer.Enabled := TRUE; | 
|---|
| 113 | end; | 
|---|
| 114 |  | 
|---|
| 115 | // data is in 2 strings | 
|---|
| 116 | // list of variable names | 
|---|
| 117 | // list of data | 
|---|
| 118 | procedure TfrmVA508HiddenJawsMainWindow.WriteData(VarName, Value: string); | 
|---|
| 119 | var | 
|---|
| 120 | offset, len: integer; | 
|---|
| 121 | begin | 
|---|
| 122 | ConverAccelChars(Value); | 
|---|
| 123 | len := length(Value); | 
|---|
| 124 | if len > 0 then | 
|---|
| 125 | begin | 
|---|
| 126 | offset := length(FData); | 
|---|
| 127 | FData := FData + Value; | 
|---|
| 128 | end | 
|---|
| 129 | else | 
|---|
| 130 | offset := 0; | 
|---|
| 131 | FVariables := FVariables + DLL_WINDOW_DELIM + VarName + DLL_WINDOW_OFFSET + | 
|---|
| 132 | IntToStr(offset) + DLL_WINDOW_LENGTH + IntToStr(len); | 
|---|
| 133 | end; | 
|---|
| 134 |  | 
|---|
| 135 | // output | 
|---|
| 136 | // caption:[next window handle]:varlen:var=offset,length:var=offset,len:data | 
|---|
| 137 | // varlen = from first to last : | 
|---|
| 138 |  | 
|---|
| 139 | procedure TfrmVA508HiddenJawsMainWindow.PostData; | 
|---|
| 140 | var | 
|---|
| 141 | DataWindow, LastWindow: TfrmVA508HiddenJawsDataWindow; | 
|---|
| 142 | Data, Output, RootOutput: string; | 
|---|
| 143 | Done, UpdateLastWindow: boolean; | 
|---|
| 144 | DataLen, Len, HandleIdx, AllowedChars, StartIndex: integer; | 
|---|
| 145 |  | 
|---|
| 146 | procedure GetDataWindow; | 
|---|
| 147 | var | 
|---|
| 148 | idx: integer; | 
|---|
| 149 | begin | 
|---|
| 150 | if assigned(DataWindow) then | 
|---|
| 151 | LastWindow := DataWindow; | 
|---|
| 152 | if FDataWindowPool.Count > 0 then | 
|---|
| 153 | begin | 
|---|
| 154 | idx := FDataWindowPool.Count-1; | 
|---|
| 155 | DataWindow := TfrmVA508HiddenJawsDataWindow(FDataWindowPool[idx]); | 
|---|
| 156 | FDataWindowPool.Delete(idx); | 
|---|
| 157 | end | 
|---|
| 158 | else | 
|---|
| 159 | begin | 
|---|
| 160 | DataWindow := TfrmVA508HiddenJawsDataWindow.Create(Self); | 
|---|
| 161 | FDataWindows.Add(DataWindow); | 
|---|
| 162 | DataWindow.HandleNeeded; | 
|---|
| 163 | Application.ProcessMessages; | 
|---|
| 164 | end; | 
|---|
| 165 | if FPostWindow = 0 then | 
|---|
| 166 | FPostWindow := DataWindow.Handle; | 
|---|
| 167 | end; | 
|---|
| 168 |  | 
|---|
| 169 | begin | 
|---|
| 170 | LastWindow := nil; | 
|---|
| 171 | DataWindow := nil; | 
|---|
| 172 | FVariables := FVariables + DLL_WINDOW_DELIM; | 
|---|
| 173 | Len := length(FVariables); | 
|---|
| 174 | Data := IntToStr(Len) + FVariables + FData; | 
|---|
| 175 | DataLen := length(Data) + 1; | 
|---|
| 176 | // Format = header  : next window handle : data | 
|---|
| 177 | RootOutput := FRootCaption + DLL_WINDOW_DELIM + DLL_WINDOW_DELIM; | 
|---|
| 178 | HandleIdx := length(RootOutput); | 
|---|
| 179 | AllowedChars := DLL_CAPTION_LIMIT - Length(RootOutput); | 
|---|
| 180 | StartIndex := 1; | 
|---|
| 181 | UpdateLastWindow := FALSE; | 
|---|
| 182 | repeat | 
|---|
| 183 | Done := TRUE; | 
|---|
| 184 | GetDataWindow; | 
|---|
| 185 | if UpdateLastWindow then | 
|---|
| 186 | begin | 
|---|
| 187 | Output := LastWindow.Caption; | 
|---|
| 188 | insert(IntToStr(DataWindow.handle), Output, HandleIdx); | 
|---|
| 189 | LastWindow.Caption := Output; | 
|---|
| 190 | UpdateLastWindow := FALSE; | 
|---|
| 191 | end; | 
|---|
| 192 | Len := DataLen - StartIndex; | 
|---|
| 193 | Output := RootOutput + copy(Data, StartIndex, AllowedChars); | 
|---|
| 194 | DataWindow.Caption := Output; | 
|---|
| 195 | if Len > AllowedChars then | 
|---|
| 196 | begin | 
|---|
| 197 | UpdateLastWindow := TRUE; | 
|---|
| 198 | Done := FALSE; | 
|---|
| 199 | inc(startIndex, AllowedChars); | 
|---|
| 200 | end; | 
|---|
| 201 | until Done; | 
|---|
| 202 | end; | 
|---|
| 203 |  | 
|---|
| 204 | procedure TfrmVA508HiddenJawsMainWindow.WndProc(var Msg: TMessage); | 
|---|
| 205 | var | 
|---|
| 206 | i: integer; | 
|---|
| 207 | data: string; | 
|---|
| 208 | begin | 
|---|
| 209 | if Msg.Msg = MessageID then | 
|---|
| 210 | begin | 
|---|
| 211 | Msg.Result := 1; | 
|---|
| 212 | data := caption; | 
|---|
| 213 | try | 
|---|
| 214 | // make sure Delphi has finished creating the form.  If we dont, JAWS can detect the | 
|---|
| 215 | // window before Delphi has finished creating it - resulting in an access violation | 
|---|
| 216 | if assigned(Self) then | 
|---|
| 217 | begin | 
|---|
| 218 | try | 
|---|
| 219 | if assigned(FComponentDataCallBackProc) then | 
|---|
| 220 | begin | 
|---|
| 221 | FPostWindow := 0; | 
|---|
| 222 | FData := ''; | 
|---|
| 223 | FVariables := ''; | 
|---|
| 224 | FDataWindowPool.Assign(FDataWindows); | 
|---|
| 225 | try | 
|---|
| 226 | FComponentDataCallBackProc(Msg.WParam, Msg.LParam); | 
|---|
| 227 | except | 
|---|
| 228 | end; | 
|---|
| 229 | // clean up unused windows | 
|---|
| 230 | for i := 0 to FDataWindowPool.Count - 1 do | 
|---|
| 231 | TfrmVA508HiddenJawsDataWindow(FDataWindowPool[i]).Caption := ''; | 
|---|
| 232 | SendReturnValue(Handle, FPostWindow); | 
|---|
| 233 | end; | 
|---|
| 234 | except | 
|---|
| 235 | end; | 
|---|
| 236 | end; | 
|---|
| 237 | finally | 
|---|
| 238 | if data = caption then | 
|---|
| 239 | begin | 
|---|
| 240 | SendReturnValue(Handle, 0); | 
|---|
| 241 | end; | 
|---|
| 242 | end; | 
|---|
| 243 | end | 
|---|
| 244 | else | 
|---|
| 245 | inherited WndProc(Msg); | 
|---|
| 246 | end; | 
|---|
| 247 |  | 
|---|
| 248 | end. | 
|---|