Subversion Repositories aysalia

Rev

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