I attempted to run my code that uses DialogBoxIndirect
to have my program dynamically, precisely, and flexibly
create a dialog template.
My code's call to GetLastError() fails with 1407,
"Cannot Find Window Class". I was able to find examples
using DialogBoxIndirect() in MSDN at
I pasted the functions in the last example on this page.
"Creating a template in memory" into my program and called
it. The example function built the DLGTEMPLATE and
associated DLGITEMTEMPLATEs in a global memory object.
The example's call to DialogBoxIndirect() then failed with
the same "Cannot Find Window Class" error.
The only thing I've been able to observe is execution
never stops at the breakpoint in the dialog procedure's
WM_INITDIALOG clause.
I usually try some things, and report the results of
those efforts to you folks. But I don't have a clue
as to what my code, and MSDN's example code, is doing
to cause this error.
Anyway, I'd appreciate any suggestions.
Thanks
Larry
The problem is that the sample thinks fields should be aligned on DWORD
boundaries, when in fact they should be aligned on WORD boundaries (the
article text backs this up). This was causing the data structures themselves
to be skewed, so the "window class" error was happening as a result of
Windows interpreting random data as a window class atom.
So it's a matter of changing the lpwAlign function,
either:
LPWORD lpwAlign ( LPWORD lpIn)
{
ULONG ul;
ul = (ULONG) lpIn;
ul++;
ul >>= 1;
ul <<= 1;
return (LPWORD) ul;
}
or, as I prefer it:
LPWORD lpwAlign ( LPWORD lpIn)
{
ULONG ul;
ul = (ULONG) lpIn;
ul = (ul + 1) & -2;
return (LPWORD) ul;
}
--
Tim Robinson (MVP, Windows SDK)
http://www.themobius.co.uk/
"Larry Lindstrom" <larryl_death...@aracnet.com> wrote in message
news:3FA4C52F...@aracnet.com...
Thanks Tim:
After posting this 44 minutes past midnight I felt I had
put a message in a fragile bottle and tossed it into a stormy
sea. I wasn't expecting a reply, and went to bed resigned to
dusting off my code to insert each control into the dialog box
manually.
The example works with your modification. Now I'm
examining it closely. I see that my function has fatal flaws,
which I'm fixing.
This operation calls out for abstraction, I'm thinking
about a function that will take a tree structure describing
the controls, and groups of controls that can be duplicated
in multiple places on the display. I have a project in mind
that would benefit from such a tool.
Thanks
Larry
Neither was I, but I had a hunch it was to do with the alignment code. I've
mentioned this to the relevant people at Microsoft, so hopefully the article
will be changed in future.
[...]
> This operation calls out for abstraction, I'm thinking
> about a function that will take a tree structure describing
> the controls, and groups of controls that can be duplicated
> in multiple places on the display. I have a project in mind
> that would benefit from such a tool.
That sounds like a good project. Dialog templates certainly do call out for
abstraction -- I hate the thought of dealing with them directly. It's such a
pain, and there's so much to go wrong (as you, and the authors of that
example, have found!).
Good luck...
>OK, I've looked through the sample and I've got it to work.
I'm trying to add a few checkboxes to the GetSaveFileName dialog,
and just today I started fiddling with that same code sample.
Synchronicity or what?
>The problem is that the sample thinks fields should be aligned
>on DWORD boundaries, when in fact they should be aligned on WORD
>boundaries (the article text backs this up). This was causing the
>data structures themselves to be skewed, so the "window class" error
>was happening as a result of Windows interpreting random data as a
>window class atom.
>
>So it's a matter of changing the lpwAlign function,
>
>either:
>
>LPWORD lpwAlign ( LPWORD lpIn)
>{
> ULONG ul;
> ul = (ULONG) lpIn;
> ul++;
> ul >>= 1;
> ul <<= 1;
> return (LPWORD) ul;
>}
>
>or, as I prefer it:
>
>LPWORD lpwAlign ( LPWORD lpIn)
>{
> ULONG ul;
> ul = (ULONG) lpIn;
> ul = (ul + 1) & -2;
> return (LPWORD) ul;
>}
Are you sure about this? Yes, the arrays that follow the template
structures must be aligned on a WORD boundary (although the creation
data array in a DLGITEMTEMPLATE is an exception, requiring DWORD
alignment). However, the DLGITEMTEMPLATE structures themselves
must be aligned on a DWORD boundary; they start off with a pair
of DWORDs. Modifying lpwAlign as you've done creates a 50% chance
that the structures won't be correctly aligned. (I've confirmed
this with memory dumps of my own test code.)
My symptom when things go wrong is that GetSaveFileName fails,
and CommDlgExtendedError returns 0xFFFF (CDERR_DIALOGFAILURE).
But changing lpwAlign hasn't been the answer for me. I've
successfully added a set of four checkboxes to the GetSaveFileName
dialog - but only if the lengths of my title strings are an even
number of characters. It appears that the creation data array
must indeed by DWORD aligned - but there must also be no space
between it and the end of the title string - so I've taken to
padding each title strings with a single blank if its length
is odd.
One quibble I do have is with the Unicode conversion:
nchar = 1 + MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
I deleted that "1 +" - according to my tests, the function already
counts the terminating null in the value it returns.
Curiouser and curiouser...
--
/~\ cgi...@kltpzyxm.invalid (Charlie Gibbs)
\ / I'm really at ac.dekanfrus if you read it the right way.
X Top-posted messages will probably be ignored. See RFC1855.
/ \ HTML will DEFINITELY be ignored. Join the ASCII ribbon campaign!
Hmm, you know you can extend common dialogs using normal dialog resources?
> Are you sure about this? Yes, the arrays that follow the template
> structures must be aligned on a WORD boundary (although the creation
> data array in a DLGITEMTEMPLATE is an exception, requiring DWORD
> alignment). However, the DLGITEMTEMPLATE structures themselves
> must be aligned on a DWORD boundary; they start off with a pair
> of DWORDs. Modifying lpwAlign as you've done creates a 50% chance
> that the structures won't be correctly aligned. (I've confirmed
> this with memory dumps of my own test code.)
MSDN confirms this, on the page for DialogBoxIndirect:
"In a standard dialog box template, the DLGTEMPLATE structure and each of
the DLGITEMTEMPLATE structures must be aligned on DWORD boundaries. The
creation data array that follows a DLGITEMTEMPLATE structure must also be
aligned on a DWORD boundary. All of the other variable-length arrays in the
template must be aligned on WORD boundaries. "
[...]
> One quibble I do have is with the Unicode conversion:
>
> nchar = 1 + MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
>
> I deleted that "1 +" - according to my tests, the function already
> counts the terminating null in the value it returns.
The Unicode conversion in the sample is presumably unnecessary if you were
willing to use lstrcpyW, lstrlenW and L"OK".
Thanks guys:
You are right Tim, MSDN does confirm that. In order to clear
up any confusion, their DLGITEMTEMPLATE page clearly states:
"The creation data array begins at the next WORD boundary after
the title array."
: )
Larry