3

I need to change the default caption of a MsgBox message box at runtime. Currently it constantly shows the value of the SetupAppTitle directive as a caption:

[Setup]
SetupAppTitle=myAppName

But this is specified at compilation time. How to do this at runtime, e.g. from a [Code] section ?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992

2 Answers2

5

I don't think changing of the application title (if possible) would be a good idea only for displaying dialog title. So I would use the Windows MessageBox which is even used by the MsgBox. Here is a simple example for Ansi/Unicode versions of Inno Setup:

[Code]
const
  MB_ICONERROR = $10;
  MB_ICONQUESTION = $20;
  MB_ICONWARNING = $30;
  MB_ICONINFORMATION = $40;

#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif

function MessageBox(hWnd: HWND; lpText, lpCaption: string;
  uType: UINT): Integer; external 'MessageBox{#AW}@user32.dll stdcall';

procedure ButtonOnClick(Sender: TObject);
begin
  MessageBox(0, 'Message Text', 'Message Caption', MB_OK or MB_ICONINFORMATION);
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
TLama
  • 75,147
  • 17
  • 214
  • 392
  • should i use the MessageBoxW (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645505%28v=vs.85%29.aspx) –  Mar 12 '12 at 16:20
  • @TLama, If there is a `PChar` in the Unicode version it might be actually defined as `PWideChar` (replace the `PAnsiChar`). That is, if the OP needs to show *Unicode* title/message (If not, you can use the Ansi version). I can't test it though... – kobik Mar 12 '12 at 16:52
  • @GregoryKotsaftis, You need to replace `PAnsiChar` to `PChar`, and test it. otherwise it's a 50/50 version – kobik Mar 12 '12 at 16:56
  • i will try to test it and report back. –  Mar 12 '12 at 17:00
  • @kobik, I've been also using only ANSI version. However I've tried to play with the Unicode one some time ago and there's no `PChar` nor `PWideChar` and in the [`reference`](http://www.jrsoftware.org/ishelp/index.php?topic=unicode) there's just a note that `string` and `Char` are now Unicode and that `PChar` has been renamed to `PAnsiChar`. But as far as I remember the compilation failed me because of missing `PChar` type, so hard to say how is declared type `PWideChar`. – TLama Mar 12 '12 at 17:01
  • still i am using an 32 & 64 bit installer (ArchitecturesInstallIn64BitMode=x64 and checks for x64 version), should i do something different? –  Mar 12 '12 at 17:02
  • 1
    @TLama, in that case I think that simply changing `PAnsiChar` to `string` will do the trick ;) – kobik Mar 12 '12 at 17:12
  • 1
    @kobik, thanks, you're right [`that`](http://www.codenewsfast.com/cnf/article/653830/waArticleBookmark.7380686) might do the trick. – TLama Mar 12 '12 at 17:15
  • 1
    @GregoryKotsaftis, there is no difference. – kobik Mar 12 '12 at 17:23
  • @fubar, answer of this user utilize exact exported data types unlike made up by the OP. Do you have a technical arguments to your feeling? Hint: `HWND != Integer`, `UINT != Cardinal`. – Victoria Nov 03 '17 at 20:43
  • @Victoria, i am using it in 3 different projects for 3 years now and it works like a charm... I guess the types have to be alias or else pls explain why does it work as expected? – fubar Dec 03 '17 at 12:20
  • [hint](https://stackoverflow.com/questions/997795/how-are-the-basic-delphi-types-related-to-each-other) – fubar Dec 03 '17 at 12:31
1

This is how i finally did it:

[Code]
{ https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505.aspx }
{ Use Windows MessageBox() function as an MsgBox() replacement. }
{ MessageBoxW is the UNICODE version of this API call. }
const
  { these are not exported in Inno Setup! }
  MB_ICONERROR = $00000010;
  MB_ICONWARNING = $00000030;
  MB_ICONINFORMATION = $00000040;
  MB_ICONQUESTION = $00000020;

function _MessageBoxW_(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal): Integer;
  external 'MessageBoxW@user32.dll stdcall';

{ Usage: SysMsgBox('Error', 'Shit happens!', MB_OK or MB_ICONERROR); }
{        res =: SysMsgBox('Question', 'blah blah', MB_YESNO or  MB_ICONQUESTION); }
function SysMsgBox(const Caption, Message: String; const Flags: Integer): Integer;
begin
  Result :=
    _MessageBoxW_(StrToInt(ExpandConstant('{wizardhwnd}')), Message, Caption, Flags);
end;

Thanks to all for your help!

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • 2
    Nice "Usage" ;) Please make sure you accept @TLama's answer as the correct one. – kobik Mar 13 '12 at 11:41
  • 1
    That was not what i needed. My solution is better since it also handles the window's "hWnd" by using StrToInt(ExpandConstant('{wizardhwnd}')). –  Mar 13 '12 at 16:41
  • I don't know in what is this better, could you elaborate please ? You don't need to specify the owner of the message box, you can keep it 0. – TLama Mar 13 '12 at 19:21
  • 1
    If you do not specify the owner of the window, you can easily loose the focus. If you click in the Setup window while a popup message is displayed, the message gets behind the Setup window when if should NOT. My solution behaves correctly, just as MsgBox() does. When popup is visible, it is tighten together with the parent window. –  Mar 14 '12 at 07:00
  • 2
    Ah, I see, you are missing the `MB_TASKMODAL` flag (`MB_TASKMODAL = $00002000;`). There are many more tags for the [`MessageBox`](http://msdn.microsoft.com/en-us/library/ms645505%28VS.85%29.aspx), kobik chose only few of them. Surely, when you have set proper window handle, it will cause blinking of the message box when you try to set the focus from it. – TLama Mar 14 '12 at 13:01
  • 1
    The popup is MODAL by default, but that has nothing to do with OWNERSHIP. Test my code and then replace the StrToInt(ExpandConstant('{wizardhwnd}')) with 0 and you will see the difference. Just try to click somewhere else when the popup is visible and you will get my point. –  Mar 14 '12 at 13:07
  • You are mixing two things together. There's a difference between modality and topmost state. You're right that the window is being always displayed as topmost, but you can focus the wizard window. If you set the `MB_TASKMODAL` flag, your window will be displayed again as topmost, but will also be modal, what means you won't be able to focus the wizard window. That's what you are calling ownership. – TLama Mar 14 '12 at 14:05
  • 1
    Sorry, but I have to say no again. If you set the parent of the window to 0 it is WAY different than to set it to an actual PARENT of that window. This is how I do it in Java (in a similar way) and this is how INNO does it. See: CodeDll.iss, function NextButtonClick at line 45... –  Mar 14 '12 at 15:57
  • 2
    Java is totally independent platform. But anyway, the only difference between if you specify the `hWnd` or use `MB_TASKMODAL` without `hWnd` specified is that in the first case your window will blink when you try to focus the wizard. In the second case won't. And it's because of that ownership ;-) – TLama Mar 14 '12 at 20:17
  • 2
    That is my point! Thanks to all for pointing me at the right direction. Still I had to quickly parse inno's code to find an answer the suited my needs... (I voted for any help I got for this one!) –  Mar 14 '12 at 20:29
  • @GregoryKotsaftis, "The popup is MODAL by default" no it's not, and this is totally wrong. the logic of Inno-Setup (from looking at the sources) is actually more complex, and if the `Application` handle is 0 it actually uses `MB_TASKMODAL`. – kobik Mar 16 '12 at 15:29
  • 1
    If `wizardhwnd` is 0 (`InitializeSetup`/`InitializeWizard`) you might want to add `MB_TASKMODAL` flag. other then that I think that your answer should have been a comment on @TLama answer or an edit of your own question. "My solution is better"... this is not *your* solution. this is an improvement of the solution provided by TLama. – kobik Mar 16 '12 at 15:46
  • 2
    check the times, @Mar 12 I had already solved this, but since I was a newbie, I could not post my answer until one day had passed. So I had to wait... I never used TLama's solution, since I already had one (the one I provided the other day). –  Mar 18 '12 at 16:57
  • 1
    you may be right about the modal issue (java that i know behaves differently) but I still believe my solution is better since it can also be used for question popups since it returns the result! –  Mar 18 '12 at 17:01
  • 1
    @gregory you did not even have the good manners to vote on TLama's answer. That is ungrateful to say the least. – David Heffernan Mar 19 '12 at 14:57
  • @DavidHeffernan, *How* do you know he did not vote on TLama's answer? – kobik Mar 19 '12 at 15:09
  • 1
    @GregoryKotsaftis, "check the times, Mar 12 I had already solved this"... This could make some sense and you should have mentioned that. I never came across such situation on SO, so I can't tell what's the proper way to handle it. BTW, TLama's answer also handles Ansi and Unicode versions of Inno-Setup. so you might want to update your answer. – kobik Mar 19 '12 at 15:20
  • 1
    @everyone I VOTED FOR ANY HELP I GOT, EVEN AT USEFULL COMMENTS! Chill out with that voting obsession! Really, come on, stop all the bitching! My God! I thought my wife was worse, but she is not! –  Mar 19 '12 at 18:47
  • @David Heffernan how did you see my votes, because it is surely wrong, i gave 3-4 votes in this. Sorry, you are wrong but quick enough with the fire (vote-down) button! –  Mar 19 '12 at 19:00
  • 1
    @David Heffernan I said so many times that I had already found an answer that fitted my needs long before TLama's response. I could not post it since that dawn reputation limit would not allow me until 24 hours had passed. I don't care about the rep but I believe my answer is WAY better and no-one will EVER change my opinion about this. Still I gave 3-4 votes that i remember and I am sorry if stackoverflow SUCKS in this! It should report the votes in details so no-none will hide behind anonymity. –  Mar 19 '12 at 19:27
  • 1
    Anyway, I am way too old for this shit! I joined mainly to help but it seems everyone's mind is focused ONLY in voting, so I am out of here for good! Not my loss anyway... –  Mar 19 '12 at 19:28
  • 1
    You can only vote once on an answer. You cannot vote more than once. I can see now that you are referring to comment votes. Your answer is hardly WAY better, but it's quite right that you should be passing the hwndParent parameter to MessageBox. The fact that you couldn't post your answer for a day is your problem. If you had already solved the problem you could have noted so in a comment and saved others from the effort they put in. Anyway, the comments that you made to TLama's answer indicate that TLama solved your problem and you then polished it. – David Heffernan Mar 19 '12 at 19:33
  • Can you please avoid the bad language and the shouting. – David Heffernan Mar 19 '12 at 19:33
  • very nice, clean and explanatory snippet. Well done. – fubar Jan 31 '21 at 21:30