|
This thread is locked; no one can reply to it. |
1
2
|
`al_show_native_message_box` buttons argument ignored |
Karadoc ~~
Member #2,749
September 2002
|
This code: Produces the attached screenshot. {"name":"606650","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/a\/aa0fb20013ef645f5ad17249012d1b5c.png","w":319,"h":174,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/a\/aa0fb20013ef645f5ad17249012d1b5c"} Based on my understanding of the manual I'd expect it to show three buttons, labeled 'A', 'B', and 'C'. I've tried a few different messagebox flags, and the problem is the same. I'm using allegro v5.1.2[1], and mingw v4.7.0. (It isn't the latest version of Allegro, but I didn't see anything about this in the changelog.) ----------- |
Arthur Kalliokoski
Second in Command
February 2005
|
I think this was discussed a few weeks ago but I can't find it now. The problem is that nobody has bothered to write a full blown modeless dialog box function for Windows. They all watch too much MSNBC... they get ideas. |
Elias
Member #358
May 2000
|
And it seems to be not easy at all, compared to OSX/GTK. But yes, if anyone has the code for it and can make a patch it would be added of course. The current implementation is this btw: https://github.com/elias-pschernig/allegro5/blob/5.1/addons/native_dialog/win_dialog.c#L238 So basically just a call to MessageBoxW. -- |
Karadoc ~~
Member #2,749
September 2002
|
Ok. I might look into adding that functionality later today. (Or rather, I will look into it, but I might give up before doing anything useful...) Is there some kind of todo list for Allegro which tracks unfinished features like this? I didn't notice anything in the manual, or any comments in the code, to indicate that this feature is incomplete on Windows. [edit] Surely there must be some libraries or something which already do this stuff. It's a pretty basic and useful task, but the winapi stuff is just too low level. ----------- |
SiegeLord
Member #7,827
October 2006
|
Karadoc ~~ said: From what I can tell, we'd need to do something like this [blogs.msdn.com], but with automatically generated parameters and style etc, and without using C++ features. That looks horribly obtuse, but not too terrible. It's fine to use C++ (I mean the OSX dialogs are implemented in ObjC) but I don't think C++ is necessary here. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Karadoc ~~
Member #2,749
September 2002
|
I've been writing some code to implement the custom buttons functionality in Allegro. My code isn't quite finished yet, but I've just tried to compile it as part of Allegro and I've run into some problems... Apparently Allegro is set up to only allow ISO C90 code, and so I'm getting error messages like this: win_dialog.c:303:4: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] win_dialog.c:308:4: error: 'for' loop initial declarations are only allowed in C99 mode Is there some good reason for enforcing C90 rather than C99? In my view, declaring variable where they are needed, and initialing variables when they are declared are both good style, and I'd rather not have to change it. In case someone is interested, here is the code I've got so far: 1int _al_show_native_message_box(ALLEGRO_DISPLAY *display,
2 ALLEGRO_NATIVE_DIALOG *fd)
3{
4 if (fd->mb_buttons && !(fd->flags & (ALLEGRO_MESSAGEBOX_OK_CANCEL | ALLEGRO_MESSAGEBOX_YES_NO)))
5 {
6 // (all of the code from the current implementation)
7 // ...
8 }
9
10 // else there are custom buttons - so things are more complex
11
12 // (new code)
13 size_t text_size = al_ustr_size_utf16(fd->mb_heading);
14 size_t title_size = al_ustr_size_utf16(fd->title);
15
16 // count the number of custom buttons
17 size_t num_buttons = 1;
18 for (ALLEGRO_USTR* i = fd->mb_buttons; *i != '\0'; i++)
19 {
20 if (*i == '|')
21 num_buttons++;
22 }
23
24 // record the starting position and length of each button name
25 size_t button_caption_length[num_buttons]; // note: this is string length, not memory size
26 ALLEGRO_USTR* button_caption_start[num_buttons];
27 button_caption_start[0] = fd->mb_buttons;
28 num_buttons = 0;
29 for (ALLEGRO_USTR* i = fd->mb_buttons; true; i++)
30 {
31 if (*i == '|' || *i == '\0')
32 {
33 button_caption_length[num_buttons] = i - button_caption_start[num_buttons];
34 num_buttons++;
35 if (*i == '\0')
36 break;
37 else
38 button_caption_start[num_buttons] = i+1;
39 }
40 }
41 ASSERT(num_buttons == sizeof(button_caption_length) / sizeof(*button_caption_length));
42
43 // Note: the sizes of the buttons, and text box, and the dialog itself are currently mostly just arbitrary numbers.
44 // Ideally these sizes should be calculated to best suit the content of the dialog.
45 const short button_width = 50;
46 const short button_height = 14;
47 short dlg_width = 200 > num_buttons*(button_width+20) ? 200 : num_buttons*(button_width+20);
48 short dlg_height = 80;
49
50 //
51 size_t dlg_buffer_size = sizeof(DLGTEMPLATE);
52 dlg_buffer_size += 2*sizeof(WORD); // menu and class (unused)
53 dlg_buffer_size += title_size; // dialog title
54
55 // text (heading and text combined)
56 // align to dword
57 {
58 int excess = dlg_buffer_size % sizeof(DWORD);
59 if (excess)
60 dlg_buffer_size += sizeof(DWORD) - excess;
61 }
62 // item data
63 dlg_buffer_size += sizeof(DLGITEMTEMPLATE);
64 dlg_buffer_size += sizeof(DWORD); // class
65 dlg_buffer_size += text_size; // the text itself
66 dlg_buffer_size += sizeof(WORD); // creation data
67
68 // similarly for each of the buttons.
69 for (size_t i = 0; i < num_buttons; i++)
70 {
71 // align to dword
72 {
73 int excess = dlg_buffer_size % sizeof(DWORD);
74 if (excess)
75 dlg_buffer_size += sizeof(DWORD) - excess;
76 }
77
78 // add the data size of this button
79 dlg_buffer_size += sizeof(DLGITEMTEMPLATE);
80 dlg_buffer_size += sizeof(DWORD); // class
81 dlg_buffer_size += button_caption_length[i]*sizeof(WCHAR); // caption
82 dlg_buffer_size += sizeof(WORD); // creation data
83 }
84
85 DLGTEMPLATE* dlg_template = al_malloc(dlg_buffer_size);
86 if (!dlg_template) {
87 // Not enough memory. :(
88 return 0;
89 }
90 dlg_template->x = 0;
91 dlg_template->y = 0;
92 dlg_template->cx = dlg_width;
93 dlg_template->cy = dlg_height;
94 dlg_template->cdit = 1 + num_buttons; // components = text + number of buttons (todo + icons for warning / error etc)
95 dlg_template->style = DS_CENTER | DS_MODALFRAME | WS_CAPTION | WS_POPUP | WS_BORDER;
96
97
98 size_t buffer_offset = sizeof(DLGTEMPLATE);
99 (WORD*)(dlg_template+buffer_offset) = 0; // menu (none)
100 buffer_offset += sizeof(WORD);
101 (WORD*)(dlg_template+buffer_offset) = 0; // class (none)
102 buffer_offset += sizeof(WORD);
103 al_ustr_encode_utf16(fd->title, (uint16_t*)(dlg_template+buffer_offset), title_size); // title
104 buffer_offset += title_size;
105
106 // dialog header complete. Now for the dialog items.
107 // First, the text.
108 buffer_offset += (sizeof(DWORD) - buffer_offset % sizeof(DWORD)) % sizeof(DWORD); // align to DWORD
109 {
110 DLGITEMTEMPLATE* item = (dlg_template+buffer_offset);
111 item->helpID = 0;
112 item->dwExtendedStyle = 0;
113 item->style = WS_CHILD | WS_VISIBLE;
114 item->x = 7;
115 item->y = 7;
116 item->cx = dlg_width - 14;
117 item->cy = dlg_height-7-button_height-7;
118 item->id = -1;
119 }
120 buffer_offset += sizeof(DLGITEMTEMPLATE);
121
122 (WORD*)(dlg_template+buffer_offset) = 0xFFFF; // pre-defined type to follow
123 (WORD*)(dlg_template+buffer_offset+sizeof(WORD)) = 0x0082; // 'static'
124 buffer_offset += 2*sizeof(WORD);
125
126 al_ustr_encode_utf16(fd->title, (uint16_t*)(dlg_template+buffer_offset), text_size); // text body
127 buffer_offset += text_size;
128 (WORD*)(dlg_template+buffer_offset) = 0; // creation data (whatever that means - we don't need it)
129 buffer_offset += sizeof(WORD);
130
131 // Next, each of the buttons.
132 for (size_t i = 0; i < num_buttons; i++)
133 {
134 buffer_offset += (sizeof(DWORD) - buffer_offset % sizeof(DWORD)) % sizeof(DWORD); // align to DWORD
135
136 DLGITEMTEMPLATE* item = (dlg_template+buffer_offset);
137 item->helpID = 0;
138 item->dwExtendedStyle = 0;
139 item->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON | (i == 0 ? WS_GROUP : 0);
140 item->x = dlg_width - (num_buttons - i) * button_width - (num_buttons + 1 - i) * 20;
141 item->y = dlg_height - button_height - 7;
142 item->cx = button_width;
143 item->cy = button_height;
144 item->id = 1000 + i;
145
146 buffer_offset += sizeof(DLGITEMTEMPLATE);
147
148 (WORD*)(dlg_template+buffer_offset) = 0xFFFF; // pre-defined type to follow
149 (WORD*)(dlg_template+buffer_offset+sizeof(WORD)) = 0x0080; // 'button'
150 buffer_offset += 2*sizeof(WORD);
151
152 al_ustr_encode_utf16(button_caption_start, (uint16_t*)(dlg_template+buffer_offset), button_caption_length[i]*sizeof(WCHAR)); // caption
153 buffer_offset += button_caption_length[i]*sizeof(WCHAR);
154 (WORD*)(dlg_template+buffer_offset) = 0;
155 buffer_offset += sizeof(WORD);
156 }
157 int result = DialogBoxIndirect(0, dlg_template, al_get_win_window_handle(display), 0);
158 al_free(dlg_template);
159 return result;
160}
As I said though, it isn't quite finished. ----------- |
Matthew Leverton
Supreme Loser
January 1999
|
Karadoc ~~ said: Is there some good reason for enforcing C90 rather than C99? Visual C++. |
Thomas Fjellstrom
Member #476
June 2000
|
Matthew Leverton said: Visual C++. he asked if there were any good reasons. -- |
torhu
Member #2,727
September 2002
|
Thomas Fjellstrom said: he asked if there were any good reasons. To annoy the Freetards |
Arthur Kalliokoski
Second in Command
February 2005
|
Sticking to a 22 year old standard instead of a 13 year old standard is good business practice! Let me see, what else was new in 1990? Tim Berners Lee proposes a "hypertext" system, a precursor to the World Wide Wait, er, Web! Windows 3.0 was brand spanking new! The Sound Blaster Pro was new! IBM introduces XGA to extend the VGA standard. The first 32 bit Amiga is introduced! Yves hasn't been born yet. Or BAF (!) I'll stop now. They all watch too much MSNBC... they get ideas. |
Elias
Member #358
May 2000
|
I wouldn't mind dropping Visual C++ support. Not for using Allegro, but for compiling it. We'd of course adjust the DLL creation process so the produced DLLs can be used with VC before doing that. But it would mean, Allegro itself could be written in proper C11. To compile it you would need to use clang or gcc or the Intel compiler or any other C11 compiler. Most VS users wouldn't compile the library themselves anyway, so nothing would change for them. They get the headers and libraries and can use Allegro. -- |
torhu
Member #2,727
September 2002
|
Elias said: But it would mean, Allegro itself could be written in proper C11. To compile it you would need to use clang or gcc or the Intel compiler or any other C11 compiler. Most VS users wouldn't compile the library themselves anyway, so nothing would change for them. Being unable to build and debug Allegro in Visual Studio could mean losing most Windows contributors. And you wouldn't have debug information for Allegro that the MSVC debugger can read. Etc. |
Trent Gamblin
Member #261
April 2000
|
I don't see what the big problem is with declaring variables at the top of functions, including loop iterators. Really not worth losing MSVC support over.
|
Thomas Fjellstrom
Member #476
June 2000
|
torhu said: Being unable to build and debug Allegro in Visual Studio could mean losing most Windows contributors. You mean almost none? If not none? We don't really have a windows dev. -- |
Trent Gamblin
Member #261
April 2000
|
I maintain the d3d port and work on opengl too . The only thing I haven't fixed is the topic of this very thread. I use MinGW myself but I may be using VC++ more for Windows 8 stuff. If I have the money to buy a Windows 8 license I intend to "port" Allegro to it (meaning have it feel like a real Windows 8 app with metro and all that, not just a compatibility app, ready for the Windows store etc.)
|
torhu
Member #2,727
September 2002
|
Thomas Fjellstrom said: You mean almost none? If not none? We don't really have a windows dev? Remember END_OF_MAIN()? That would probably still be there if someone that use MSVC as their main development tool hadn't realized that it's not needed. It would have stayed because "the stupid MSVC crap can't do things in a sane way". And nobody would know that the real reason was just that the Allegro dev team lacked familiarity with the MSVC tool chain. And this was done by an outside contributor who probably wouldn't bother if he couldn't build and debug Allegro in his beloved MSVC. And I should know, as it was me Trent Gamblin said: I don't see what the big problem is with declaring variables at the top of functions, including loop iterators. Really not worth losing MSVC support over. Me neither. I see how it's annoying having to get used to a slightly different (and inferior) style of programming if you've never had to do it like this before. And even worse when it's evil Microsoft's fault. But it's still pretty much the same C that we all know and love. |
Karadoc ~~
Member #2,749
September 2002
|
Well, I'd vote in favour of dropping Visual C++ support for building Allegro; but since I'm not a significant contributor to Allegro, I don't think my vote should count for much. The archaic rules about variable declarations are pretty annoying[1]; but more generally, I just don't think Allegro should allow itself to be held back by just because one compiler is no longer being updated. There are a bunch of new C features which some Allegro developers may want to use at some point. And although it may not be easy to come up with a priori reasons for using any given feature, I think that the question of whether or not developers can use any given feature should be "is this standard C" rather than "is this supported by Microsoft?" For me, this kind of VC++ stuff is bad for morale. Instead of thinking about making high quality code, I just end up getting frustrated at Microsoft and it makes me want to avoid working in such an environment. References
----------- |
Thomas Fjellstrom
Member #476
June 2000
|
torhu said: And this was done by an outside contributor who probably wouldn't bother if he couldn't build and debug Allegro in his beloved MSVC. And I should know, as it was me You are welcome to become the full time windows maintainer -- |
Peter Wang
Member #23
April 2000
|
We're not dropping MSVC support over this trivial issue.
|
torhu
Member #2,727
September 2002
|
Thomas Fjellstrom said: You are welcome to become the full time windows maintainer Thanks, but just the thought of making any commitment to an unpaid project makes me feel a bit stressed right now Karadoc, most of your reasons are valid but pretty insignificant in practice. |
Thomas Fjellstrom
Member #476
June 2000
|
torhu said: Thanks, but just the thought of making any commitment to an unpaid project makes me feel a bit stressed right now That busy eh? -- |
Karadoc ~~
Member #2,749
September 2002
|
Ok. Moving on from that VC++ stuff, and back to implementing this custom buttons functionality... In the code I posted, one of the big and obvious holes is that the way I've handled the buttons names is broken. I'm going to fix that now; but I'm not familiar with how to handle unicode strings, so I just want to do a quick sanity check here before I write the code. (Somewhat embarrassingly, I didn't even realise that unicode character had variable length until a few minutes ago. I thought UTF-16 just meant all characters were 16 bit numbers or something like that.) As I understand it, we start with a ALLEGRO_USTR called mb_buttons which contains a list of button names separated by '|' characters. To use this in the Windows API, we'll need to encode the individual button names into the correct places in the dialog template buffer, as UTF-16 strings. I've just browsed through some of the Allegro API to see how this can be done. I now know how to iterate through the characters in mb_buttons to find the starting position and the size of each button name. But unfortunately I can't see a way to encode one of these substrings directly into the dialog buffer. What I'd like is to use a function like al_ustr_encode_utf16_substr to encode the button names directly onto the buffer. Unfortunately, that function doesn't exist. So it seems to me that I have to use al_ustr_dup_substr to create separate `ALLEGRO_USTR`s for each button name and then use al_ustr_encode_utf16 to encode each of them into their place in the dialog buffer. Does that sound about right? It sucks a bit, because its a bunch of allocating/copying/freeing just to move data from one API to the other. ----------- |
Peter Wang
Member #23
April 2000
|
al_ref_ustr
|
Karadoc ~~
Member #2,749
September 2002
|
Right. al_ref_ustr is the thing to use; and I've worked around the variable declaration problem by putting a bunch of braces all over the place. I've now finished what I was trying to implement; but I'm pretty disappointed with how it turned out. It doesn't really look 'native' at all. It looks like quite bad. {"name":"606671","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/b\/a\/ba6f742214ab05bcfd8921e98b5d9082.png","w":466,"h":188,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/b\/a\/ba6f742214ab05bcfd8921e98b5d9082"} I assumed that if I didn't specify a font, Windows would automatically pick whatever the normal font is – but unfortunately it actually just uses a trashy looking system font. Also, my current implementation doesn't make any attempt to make the box big enough to fit the text. The height of the box is the same regardless of the text. So.. I guess the main shortcomings of my implementation are as follows:
... So the result is pretty ugly, but at least it has the correct buttons! I'm not intending to work on this again in the near future, but if someone else wants to have a go at it, or if you think this is good enough to put into Allegro, then here's the code: 1// DialogProc callback for customized windows dialog boxes
2INT_PTR CALLBACK _al_winAPI_DlgProc(HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
3{
4 (void)lParam; // unused
5 if (wm == WM_INITDIALOG)
6 return TRUE;
7 if (wm == WM_COMMAND)
8 {
9 int control_id = LOWORD(wParam);
10
11 if (control_id > 1000)
12 {
13 EndDialog(hwnd, control_id-1000);
14 return TRUE;
15 }
16 }
17 return FALSE;
18}
19
20int _al_show_native_message_box(ALLEGRO_DISPLAY *display,
21 ALLEGRO_NATIVE_DIALOG *fd)
22{
23 /* heading + text are combined together */
24
25 if (al_ustr_size(fd->mb_heading))
26 al_ustr_append_cstr(fd->mb_heading, "\n\n");
27
28 al_ustr_append(fd->mb_heading, fd->mb_text);
29
30 // If there are no custom button names, then we can use a standard Windows message box.
31 if (!fd->mb_buttons || (fd->flags & (ALLEGRO_MESSAGEBOX_OK_CANCEL | ALLEGRO_MESSAGEBOX_YES_NO)))
32 {
33 UINT type = 0;
34 int result;
35
36 uint16_t *wide_text, *wide_title;
37 size_t text_len, title_len;
38
39 /* Note: the message box code cannot assume that Allegro is installed. */
40
41 if (fd->flags & ALLEGRO_MESSAGEBOX_QUESTION)
42 type |= MB_ICONQUESTION;
43 else if (fd->flags & ALLEGRO_MESSAGEBOX_WARN)
44 type |= MB_ICONWARNING;
45 else if (fd->flags & ALLEGRO_MESSAGEBOX_ERROR)
46 type |= MB_ICONERROR;
47 else
48 type |= MB_ICONINFORMATION;
49
50 if (fd->flags & ALLEGRO_MESSAGEBOX_YES_NO)
51 type |= MB_YESNO;
52 else if (fd->flags & ALLEGRO_MESSAGEBOX_OK_CANCEL)
53 type |= MB_OKCANCEL;
54
55 text_len = al_ustr_size_utf16(fd->mb_heading);
56 title_len = al_ustr_size_utf16(fd->title);
57
58 wide_text = al_malloc(text_len + 1);
59 if (!wide_text)
60 return 0;
61
62 wide_title = al_malloc(title_len + 1);
63 if (!wide_title) {
64 al_free(wide_text);
65 return 0;
66 }
67
68 al_ustr_encode_utf16(fd->mb_heading, wide_text, text_len);
69 al_ustr_encode_utf16(fd->title, wide_title, title_len);
70
71 result = MessageBoxW(al_get_win_window_handle(display),
72 (LPCWSTR) wide_text, (LPCWSTR) wide_title, type);
73
74 al_free(wide_text);
75 al_free(wide_title);
76
77 if (result == IDYES || result == IDOK)
78 return 1;
79 else
80 return 0;
81 }
82 // else there are custom buttons - so things are more complex
83 else
84 {
85 size_t text_size = al_ustr_size_utf16(fd->mb_heading);
86 size_t title_size = al_ustr_size_utf16(fd->title);
87
88 size_t num_buttons;
89 int* button_caption_start;
90 int* button_caption_end;
91
92 // count the number of custom buttons
93 {
94 int offset = 0;
95 num_buttons = 0;
96 do
97 {
98 offset = al_ustr_find_chr(fd->mb_buttons, offset, '|');
99 al_ustr_next(fd->mb_buttons, &offset);
100 num_buttons++;
101 } while (offset > 0);
102 }
103 ASSERT(num_buttons > 0);
104
105 // record the start and end of each button name
106 button_caption_start = al_malloc(sizeof(*button_caption_start)*num_buttons);
107 button_caption_end = al_malloc(sizeof(*button_caption_end)*num_buttons);
108 if (!button_caption_start || !button_caption_end)
109 {
110 // failed to allocate memory for at least one of the arrays
111 al_free(button_caption_start);
112 al_free(button_caption_end);
113 return 0;
114 }
115
116 // record the start and end of each button name
117 {
118 int offset = 0;
119 num_buttons = 0;
120 do
121 {
122 button_caption_start[num_buttons] = offset;
123 offset = al_ustr_find_chr(fd->mb_buttons, offset, '|');
124 button_caption_end[num_buttons] = offset;
125 al_ustr_next(fd->mb_buttons, &offset);
126 num_buttons++;
127 } while (offset > 0);
128 button_caption_end[num_buttons-1] = al_ustr_size(fd->mb_buttons);
129 }
130
131 {
132 // Note: the sizes of the buttons, and text box, and the dialog itself are currently mostly just arbitrary numbers.
133 // Ideally these sizes should be calculated to best suit the content of the dialog.
134 const short button_width = 50;
135 const short button_height = 14;
136 short dlg_width = 200 > 20+num_buttons*(button_width+20) ? 200 : 20+num_buttons*(button_width+20);
137 short dlg_height = 80;
138
139 //
140 int result;
141 size_t i; // generic iterator
142 DLGTEMPLATE* dlg_template;
143 BYTE* buffer;
144 size_t dlg_buffer_size = sizeof(DLGTEMPLATE);
145 dlg_buffer_size += 2*sizeof(WORD); // menu and class (unused)
146 dlg_buffer_size += title_size; // dialog title
147
148 // text (heading and text combined)
149 dlg_buffer_size += (sizeof(DWORD) - dlg_buffer_size % sizeof(DWORD)) % sizeof(DWORD); // align to DWORD
150
151 // item data
152 dlg_buffer_size += sizeof(DLGITEMTEMPLATE);
153 dlg_buffer_size += sizeof(DWORD); // class
154 dlg_buffer_size += text_size; // the text itself
155 dlg_buffer_size += sizeof(WORD); // creation data
156
157 // similarly for each of the buttons.
158 for (i = 0; i < num_buttons; i++)
159 {
160 dlg_buffer_size += (sizeof(DWORD) - dlg_buffer_size % sizeof(DWORD)) % sizeof(DWORD); // align to DWORD
161
162 // add the data size of this button
163 dlg_buffer_size += sizeof(DLGITEMTEMPLATE);
164 dlg_buffer_size += sizeof(DWORD); // class
165 // caption
166 {
167 ALLEGRO_USTR_INFO str_info;
168 const ALLEGRO_USTR* sub_string = al_ref_ustr(&str_info, fd->mb_buttons, button_caption_start[i], button_caption_end[i]);
169 size_t caption_size = al_ustr_size_utf16(sub_string);
170 dlg_buffer_size += caption_size;
171 }
172 dlg_buffer_size += sizeof(WORD); // creation data
173 }
174
175 dlg_template = al_malloc(dlg_buffer_size);
176 if (!dlg_template)
177 {
178 // Not enough memory. :(
179 al_free(button_caption_start);
180 al_free(button_caption_end);
181 return 0;
182 }
183 dlg_template->x = 0;
184 dlg_template->y = 0;
185 dlg_template->cx = dlg_width;
186 dlg_template->cy = dlg_height;
187 dlg_template->cdit = 1 + num_buttons; // components = text + number of buttons (todo + icons for warning / error etc)
188 dlg_template->style = DS_CENTER | DS_MODALFRAME | WS_CAPTION | WS_POPUP | WS_BORDER;
189 dlg_template->dwExtendedStyle = 0;
190
191 buffer = (BYTE*)dlg_template;
192 buffer += sizeof(DLGTEMPLATE);
193 *(WORD*)buffer = 0; // menu (none)
194 buffer += sizeof(WORD);
195 *(WORD*)buffer = 0; // class (none)
196 buffer += sizeof(WORD);
197 al_ustr_encode_utf16(fd->title, (uint16_t*)buffer, title_size); // title
198 buffer += title_size;
199
200 // dialog header complete. Now for the dialog items.
201 // First, the text.
202 buffer += (sizeof(DWORD) - (buffer - (BYTE*)dlg_template) % sizeof(DWORD)) % sizeof(DWORD); // align to DWORD
203 {
204 DLGITEMTEMPLATE* item = (DLGITEMTEMPLATE*)(buffer);
205 item->dwExtendedStyle = 0;
206 item->style = WS_CHILD | WS_VISIBLE;
207 item->x = 7;
208 item->y = 7;
209 item->cx = dlg_width - 14;
210 item->cy = dlg_height-7-button_height-7;
211 item->id = -1;
212 }
213 buffer += sizeof(DLGITEMTEMPLATE);
214
215 *(WORD*)buffer = 0xFFFF; // pre-defined type to follow
216 *(WORD*)(buffer+sizeof(WORD)) = 0x0082; // 'static'
217 buffer += 2*sizeof(WORD);
218
219 al_ustr_encode_utf16(fd->mb_heading, (uint16_t*)buffer, text_size); // text body
220 buffer += text_size;
221 *(WORD*)buffer = 0; // creation data (whatever that means - we don't need it)
222 buffer += sizeof(WORD);
223
224 // Next, each of the buttons.
225 for (i = 0; i < num_buttons; i++)
226 {
227 buffer += (sizeof(DWORD) - (buffer - (BYTE*)dlg_template) % sizeof(DWORD)) % sizeof(DWORD); // align to DWORD
228 {
229 DLGITEMTEMPLATE* item = (DLGITEMTEMPLATE*)buffer;
230 item->dwExtendedStyle = 0;
231 item->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON | (i == 0 ? WS_GROUP : 0);
232 item->x = dlg_width - (num_buttons - i) * (button_width+20);
233 item->y = dlg_height - button_height - 7;
234 item->cx = button_width;
235 item->cy = button_height;
236 item->id = 1000 + i + 1;
237 // Note: item id will determine dialog return value. See _al_winAPI_DlgProc.
238 }
239 buffer += sizeof(DLGITEMTEMPLATE);
240
241 *(WORD*)buffer = 0xFFFF; // pre-defined type to follow
242 *(WORD*)(buffer+sizeof(WORD)) = 0x0080; // 'button'
243 buffer += 2*sizeof(WORD);
244
245 // caption
246 {
247 ALLEGRO_USTR_INFO str_info;
248 const ALLEGRO_USTR* sub_string = al_ref_ustr(&str_info, fd->mb_buttons, button_caption_start[i], button_caption_end[i]);
249 size_t caption_size = al_ustr_size_utf16(sub_string);
250
251 al_ustr_encode_utf16(sub_string, (uint16_t*)buffer, caption_size);
252 buffer += caption_size;
253 }
254 *(WORD*)buffer = 0;
255 buffer += sizeof(WORD);
256 }
257 ASSERT(buffer - (BYTE*)dlg_template == (int)dlg_buffer_size);
258 result = DialogBoxIndirect(0, dlg_template, al_get_win_window_handle(display), _al_winAPI_DlgProc);
259 al_free(dlg_template);
260 al_free(button_caption_start);
261 al_free(button_caption_end);
262 return result == -1 ? 0 : result;
263 }
264 }
265}
Unless someone wants to make a better version, I think that this version should be put into Allegro so that at least then the function will do what the manual says it should do. The previous Allegro functionality for the cases without custom buttons is unchanged, so this ugliness wouldn't be a regression. [edit] ----------- |
weapon_S
Member #7,859
October 2006
|
Karadoc ~~ said: /* Note: the message box code cannot assume that Allegro is installed. */ That's a PITA, I guess. |
|
1
2
|