Rev 16 | Rev 20 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
9 | daniel-mar | 1 | program AyDos; |
2 | |||
16 | daniel-mar | 3 | // Aysalia DOS Launcher |
4 | // Revision 2018-12-06 |
||
5 | // (C) 2018 Daniel Marschall, ViaThinkSoft |
||
6 | |||
7 | // This launcher does launch DOSBox with the correct *.conf file, |
||
8 | // centers the window and changes the window title and icon at runtime. |
||
9 | |||
9 | daniel-mar | 10 | uses |
11 | SysUtils, |
||
12 | ShellAPI, |
||
16 | daniel-mar | 13 | Windows, |
14 | Messages; |
||
9 | daniel-mar | 15 | |
16 | {$R *.RES} |
||
17 | |||
16 | daniel-mar | 18 | const |
19 | DOSBOX_EXE = 'DOSBox.exe'; |
||
20 | |||
21 | var |
||
22 | hPsApiDll: cardinal; |
||
23 | |||
24 | (* |
||
25 | function GetModuleFileNameEx(inProcess: THandle; inModule: THandle; |
||
26 | Filename: PChar; size: DWord): DWord; stdcall; |
||
27 | external 'psapi.dll' name 'GetModuleFileNameExA'; |
||
28 | *) |
||
29 | {$IFDEF UNICODE} |
||
19 | daniel-mar | 30 | function GetModuleFileNameEx(inProcess: THandle; inModule: THandle; Filename: PWideChar; size: DWord): Integer; |
16 | daniel-mar | 31 | type |
32 | TGetModuleFileNameExFunc = function (inProcess: THandle; inModule: THandle; Filename: PWideChar; size: DWord): DWord; stdcall; |
||
33 | var |
||
34 | funcGetModuleFileNameEx: TGetModuleFileNameExFunc; |
||
35 | begin |
||
36 | if psAPIHandle <> 0 then |
||
37 | begin |
||
19 | daniel-mar | 38 | @funcGetModuleFileNameEx := GetProcAddress(psAPIHandle, 'GetModuleFileNameExW'); |
39 | if Assigned(funcGetModuleFileNameEx) then |
||
16 | daniel-mar | 40 | result := funcGetModuleFileNameEx(inProcess, inModule, Filename, size) |
41 | else |
||
19 | daniel-mar | 42 | result := -1; |
16 | daniel-mar | 43 | end |
19 | daniel-mar | 44 | else result := -2; |
16 | daniel-mar | 45 | end; |
46 | {$ELSE} |
||
19 | daniel-mar | 47 | function GetModuleFileNameEx(inProcess: THandle; inModule: THandle; Filename: PAnsiChar; size: DWord): Integer; |
16 | daniel-mar | 48 | type |
49 | TGetModuleFileNameExFunc = function (inProcess: THandle; inModule: THandle; Filename: PAnsiChar; size: DWord): DWord; stdcall; |
||
50 | var |
||
19 | daniel-mar | 51 | funcGetModuleFileNameEx: TGetModuleFileNameExFunc; |
16 | daniel-mar | 52 | begin |
53 | if hPsApiDll <> 0 then |
||
54 | begin |
||
19 | daniel-mar | 55 | @funcGetModuleFileNameEx := GetProcAddress(hPsApiDll, 'GetModuleFileNameExA'); |
56 | if Assigned(funcGetModuleFileNameEx) then |
||
16 | daniel-mar | 57 | result := funcGetModuleFileNameEx(inProcess, inModule, Filename, size) |
58 | else |
||
19 | daniel-mar | 59 | result := -1; |
16 | daniel-mar | 60 | end |
19 | daniel-mar | 61 | else result := -2; |
16 | daniel-mar | 62 | end; |
63 | {$ENDIF} |
||
64 | |||
65 | var |
||
66 | hIcon: THandle = 0; |
||
67 | bCeneredOnce: boolean = false; |
||
68 | |||
69 | procedure ChangeTitleAndIcon(hWnd: Thandle); |
||
70 | var |
||
71 | Title: array[0..255] of Char; |
||
72 | const |
||
73 | TargetWinWidth = 640; |
||
74 | TargetWinHeight = 480; |
||
75 | begin |
||
76 | ZeroMemory(@Title, sizeof(Title)); |
||
77 | GetWindowText(hWnd, @Title, sizeof(Title)-1); |
||
78 | |||
79 | // Center window (once) |
||
80 | if (Title = 'DOSBox') and not bCeneredOnce then |
||
81 | begin |
||
82 | MoveWindow(hWnd, GetSystemMetrics(SM_CXSCREEN) div 2 - TargetWinWidth div 2, |
||
83 | GetSystemMetrics(SM_CYSCREEN) div 2 - TargetWinHeight div 2, |
||
84 | TargetWinWidth, |
||
85 | TargetWinHeight, |
||
86 | true); |
||
87 | bCeneredOnce := true; |
||
88 | end; |
||
89 | |||
90 | // Change window title |
||
91 | if Pos('AYDOS1', Title) > 0 then |
||
92 | SetWindowText(hWnd, 'Aysalia DOS I') |
||
93 | else if Pos('AYDOS2', Title) > 0 then |
||
94 | SetWindowText(hWnd, 'Aysalia DOS II') |
||
95 | else |
||
96 | SetWindowText(hWnd, 'Aysalia DOS'); |
||
97 | |||
98 | // Change window and taskbar icon |
||
99 | if hIcon > 0 then |
||
100 | begin |
||
101 | // Change both icons to the same icon handle. |
||
102 | SendMessage(hWnd, WM_SETICON, ICON_SMALL, hIcon); |
||
103 | SendMessage(hWnd, WM_SETICON, ICON_BIG, hIcon); |
||
104 | |||
105 | // This will ensure that the application icon gets changed too. |
||
106 | SendMessage(GetWindow(hWnd, GW_OWNER), WM_SETICON, ICON_SMALL, hIcon); |
||
107 | SendMessage(GetWindow(hWnd, GW_OWNER), WM_SETICON, ICON_BIG, hIcon); |
||
108 | end; |
||
109 | end; |
||
110 | |||
111 | function EnumWindowsProc(Handle: hWnd; dummy: DWORD): BOOL; stdcall; |
||
112 | var |
||
113 | Title: array[0..255] of Char; |
||
19 | daniel-mar | 114 | WinFileName: array[0..MAX_PATH] of Char; |
16 | daniel-mar | 115 | var |
19 | daniel-mar | 116 | PID: DWORD; |
117 | hProcess: THandle; |
||
118 | Len: Integer; |
||
16 | daniel-mar | 119 | begin |
120 | Result := True; |
||
19 | daniel-mar | 121 | ZeroMemory(@WinFileName, sizeof(WinFileName)); |
122 | GetWindowThreadProcessId(Handle, @PID); |
||
16 | daniel-mar | 123 | hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, PID); |
19 | daniel-mar | 124 | Len := GetModuleFileNameEx(hProcess, 0, WinFileName, sizeof(WinFileName)-1); |
16 | daniel-mar | 125 | if Len > 0 then |
126 | begin |
||
127 | // GetModuleFileNameEx is available on newer operating systems; |
||
128 | // it ensures that we find the correct window by checking its EXE filename. |
||
129 | if SameText(WinFileName, ExtractFilePath(ParamStr(0)) + DOSBOX_EXE) then |
||
130 | begin |
||
131 | Result := False; // stop enumeration |
||
132 | ChangeTitleAndIcon(Handle); |
||
133 | end; |
||
134 | end |
||
19 | daniel-mar | 135 | else if Len < 0 then |
16 | daniel-mar | 136 | begin |
137 | // At Win9x, there is no psapi.dll, so we try it the old fashioned way, |
||
138 | // finding the window by parts of its title |
||
139 | ZeroMemory(@Title, sizeof(Title)); |
||
140 | GetWindowText(Handle, Title, sizeof(Title)-1); |
||
141 | if IsWindowVisible(Handle) then |
||
142 | begin |
||
143 | if (title = 'DOSBox') or ((Pos('DOSBox ', title) > 0) and |
||
144 | (Pos('Cpu speed', title) > 0)) then |
||
145 | begin |
||
146 | Result := False; // stop enumeration |
||
147 | ChangeTitleAndIcon(Handle); |
||
148 | end; |
||
149 | end; |
||
150 | end; |
||
151 | end; |
||
152 | |||
9 | daniel-mar | 153 | function ShellExecuteWait(hWnd: HWND; Operation, FileName, Parameters, |
154 | Directory: PAnsiChar; ShowCmd: Integer): DWord; |
||
155 | var |
||
156 | Info: TShellExecuteInfo; |
||
157 | pInfo: PShellExecuteInfo; |
||
158 | begin |
||
159 | pInfo := @Info; |
||
160 | with Info do |
||
161 | begin |
||
16 | daniel-mar | 162 | cbSize := SizeOf(Info); |
163 | fMask := SEE_MASK_NOCLOSEPROCESS; |
||
164 | wnd := hWnd; |
||
165 | lpVerb := Operation; |
||
19 | daniel-mar | 166 | lpFile := FileName; |
9 | daniel-mar | 167 | lpParameters := PChar(Parameters + #0); |
16 | daniel-mar | 168 | lpDirectory := PChar(Directory); |
169 | nShow := ShowCmd; |
||
170 | hInstApp := 0; |
||
9 | daniel-mar | 171 | end; |
172 | ShellExecuteEx(pInfo); |
||
173 | |||
174 | repeat |
||
19 | daniel-mar | 175 | result := WaitForSingleObject(Info.hProcess, 10); |
16 | daniel-mar | 176 | EnumWindows(@EnumWindowsProc, 0); |
19 | daniel-mar | 177 | until (result <> WAIT_TIMEOUT); |
9 | daniel-mar | 178 | end; |
179 | |||
16 | daniel-mar | 180 | function Main: Integer; |
9 | daniel-mar | 181 | var |
182 | sFile: string; |
||
183 | begin |
||
16 | daniel-mar | 184 | ShellExecuteWait(0, 'open', DOSBOX_EXE, '-noconsole -conf DOSBox.conf', |
9 | daniel-mar | 185 | PChar(ExtractFilePath(ParamStr(0))), SW_NORMAL); |
186 | |||
19 | daniel-mar | 187 | sFile := IncludeTrailingBackSlash(ExtractFilePath(ParamStr(0))) + 'stdout.txt'; |
9 | daniel-mar | 188 | if FileExists(sFile) then DeleteFile(PChar(sFile)); |
189 | |||
19 | daniel-mar | 190 | sFile := IncludeTrailingBackSlash(ExtractFilePath(ParamStr(0))) + 'stderr.txt'; |
9 | daniel-mar | 191 | if FileExists(sFile) then DeleteFile(PChar(sFile)); |
16 | daniel-mar | 192 | |
193 | result := 0; |
||
194 | end; |
||
195 | |||
196 | begin |
||
19 | daniel-mar | 197 | hPsApiDll := LoadLibrary('psapi.dll'); |
198 | try |
||
199 | hIcon := LoadIcon(hInstance, 'MainIcon'); |
||
200 | ExitCode := Main; |
||
201 | finally |
||
202 | FreeLibrary(hPsApiDll); |
||
203 | end; |
||
9 | daniel-mar | 204 | end. |