Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

RFC: Ch 2 of An intro to C++ Windows API-level programming

0 views
Skip to first unread message

Alf P. Steinbach

unread,
Apr 10, 2006, 7:59:21 AM4/10/06
to
<url: http://home.no.net/dubjai/win32apitut/02.pdf>.
Contents:
2 A bare-bones micro-framework.
2.1 Directories & the idea of self-documenting include directives.
2.2 A wrapper for <windows.h>.
2.3 A Unicode command line arguments module / using ScopeGuard.
2.4 Unicode conversion support / using double-tap API calls.
2.5 Obtaining Windows API failure info (non-reusable example).


Earlier (a few days ago) I posted a request for comments on chapter 1;
thanks to all who responded.

<url: http://home.no.net/dubjai/win32apitut/01.pdf>.
Contents:
1 Accessing the Windows API
1.1 Prerequisites.
1.2 A simplest doing-it-right message box “Hello, world!”.
1.3 GUI versus console program files (Windows subsystems).
1.4 GUI programs that use standard i/o streams.
1.5 The WinMain function.
1.6 Unicode, function macros, and the Unicode startup functions.
1.7 Using standard i/o-streams in a Unicode program.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Lucian Wischik

unread,
Apr 10, 2006, 11:25:14 AM4/10/06
to
"Alf P. Steinbach" <al...@start.no> wrote:
><url: http://home.no.net/dubjai/win32apitut/02.pdf>.
>Contents:
>2 A bare-bones micro-framework.
>2.1 Directories & the idea of self-documenting include directives.
>2.2 A wrapper for <windows.h>.

I specifically think it's a bad idea to put these defines in a header.
(1) it leads to you doing all those tests for whether something's
already defined or not, (2) it's possible to forget it in one of your
modules.

I think it's better to define things like UNICODE, STRICT, ... on the
compiler command-line switches.

--
Lucian

Alf P. Steinbach

unread,
Apr 10, 2006, 11:47:34 AM4/10/06
to
* Lucian Wischik:

Regarding UNICODE, either the code requires that this symbol is defined,
or it requires that it's not defined: there's no UNICODE-agnostic code
when programming at the Windows API level. Therefore the UNICODE
definition belongs in the code, preferably centralised (because usually
it's a global property, not a per-module property). Defining it in the
command line is akin to writing a program as simply the symbol OSTRICH,
then define OSTRICH as the real program text in the command line. ;-)

STRICT is required for C++. Therefore it belongs in the code. Always:
there's no question of not defining STRICT, except for purposes of
illustrating that it's a bad idea.

Now regarding your point (1), centralizing these common symbols avoids
precisely the problem you state that that causes, and regarding your
point (2), the same: it's hard to imagine how you could have come to
those contrary conclusions -- are you trolling?

But if you're not, thanks for expressing your thoughts.

Perhaps it means that it's not as obvious as I assumed when I wrote this?

Lucian Wischik

unread,
Apr 10, 2006, 1:10:33 PM4/10/06
to
"Alf P. Steinbach" <al...@start.no> wrote:
>Defining it in the
>command line is akin to writing a program as simply the symbol OSTRICH,
>then define OSTRICH as the real program text in the command line. ;-)

I don't see the analogy. You put things in the command line that
control global aspects of how compilation is done. The command line is
*THE MOST* global place to put them. You put other directives there to
control how strict the compiler will be (e.g. warning level). And
STRICT is just another one of these.


>STRICT is required for C++. Therefore it belongs in the code.

I don't think that's a real "therefore" argument. "A C++ compiler is
required for C++. Therefore it belongs in the code." For your argument
to flow logically (and for me to understand it), you need to make it
more precise.

"linking with winmm.lib is required for C++ coding of multimedia.
Therefore the link directive belongs in the code."

>Now regarding your point (1), centralizing these common symbols avoids
>precisely the problem you state that that causes

Command-line switches are even more central than a .h file that
everyone's expected to include, they're a more robust/central way of
ensuring that everything is indeed compiled with these defines.

--
Lucian

Alf P. Steinbach

unread,
Apr 10, 2006, 1:16:35 PM4/10/06
to
* Lucian Wischik:

> "Alf P. Steinbach" <al...@start.no> wrote:
>> Defining it in the
>> command line is akin to writing a program as simply the symbol OSTRICH,
>> then define OSTRICH as the real program text in the command line. ;-)
>
> I don't see the analogy. You put things in the command line that
> control global aspects of how compilation is done. The command line is
> *THE MOST* global place to put them. You put other directives there to
> control how strict the compiler will be (e.g. warning level). And
> STRICT is just another one of these.

No, for C++ STRICT is not "how strict", and it's not a warning level.
It is the difference between code that compiles, and code that don't.
If the code uses the relevant declarations (dialog functions spring to
mind).


>> STRICT is required for C++. Therefore it belongs in the code.
>
> I don't think that's a real "therefore" argument. "A C++ compiler is
> required for C++. Therefore it belongs in the code." For your argument
> to flow logically (and for me to understand it), you need to make it
> more precise.

Well, you started with a flawed premise.

Try once more with the explanation above. ;-)

Lucian Wischik

unread,
Apr 10, 2006, 3:10:06 PM4/10/06
to
"Alf P. Steinbach" <al...@start.no> wrote:
>>> STRICT is required for C++. Therefore it belongs in the code.
>>
>> I don't think that's a real "therefore" argument. "A C++ compiler is
>> required for C++. Therefore it belongs in the code." For your argument
>> to flow logically (and for me to understand it), you need to make it
>> more precise.
>
>Well, you started with a flawed premise.
>Try once more with the explanation above. ;-)

My objection holds with the obvious weaker premise: you put other
directives there to determine whether the code will compile+link, and
whether the output will be generated, and which will affect the
correctness of the output.

Example: if you're an FxCop shop, then violating FxCop rules means
your output can't be used, giving the same practical effect as failing
to compile.

Example: if you compile for one target vs another it changes the
sizeof(int) and so can change the meaning of everything.


But really we're getting into pointless semantics here. I'm just
waiting for you to characterise what things are acceptable to put in
compiler switches, and what things not.

--
Lucian

Alf P. Steinbach

unread,
Apr 10, 2006, 10:31:58 PM4/10/06
to
* Lucian Wischik:

> My objection holds with the obvious weaker premise: you put other
> directives [in the command line] to determine whether the code will

> compile+link, and whether the output will be generated, and which
> will affect the correctness of the output.

I think you mean to ask here, so why not STRICT (for C++ Windows API)?

I don't think one can forbid someone from doing that. It's much like
int main versus void main. One camp says that int main is the only
valid way, and nothing else has ever been valid, in C or C++; and the
other camp insists that void main, although more to write, is in some
sense more logical and natural and should have been valid and is in
practice supported by their favorite compiler (then there is of course
the camp of people who wan to just write main, no int or void or stuff).

So with all these differences of opinion (int, which is the only valid
choice, void, which some feel is more natural but isn't valid and isn't
supported by all compilers, nothing, which is much less to write, and
perhaps just as natural as void, but suffers from the same problems as
void) shouldn't main's result type be configured via a macro? I don't
think so. If someone did that, I'd think it was a joke. :-)


> Example: if you're an FxCop shop, then violating FxCop rules means
> your output can't be used, giving the same practical effect as failing
> to compile.
>
> Example: if you compile for one target vs another it changes the
> sizeof(int) and so can change the meaning of everything.
>
>
> But really we're getting into pointless semantics here. I'm just
> waiting for you to characterise what things are acceptable to put in
> compiler switches, and what things not.

I'm not sure what you mean by "acceptable" (to whom? for what?), but see
above.

Also, if something is a fixed choice, should never vary (as with STRICT
for C++), then I think it's a good idea to move that choice from the
build configuration to the code, if possible, so that others won't have
to engage in detective work to build the thing but can rely on defaults.

One can of course always put a comment in the code, "requires this or
that", but it's generally a bad idea to express in comments what can be
expressed simply and directly in the code itself (so that it's enforced
and checked and automatic).


Cheers, and thanks for that feedback,

- Alf

Alan Johnson

unread,
Apr 10, 2006, 10:33:34 PM4/10/06
to
Lucian Wischik wrote:

> But really we're getting into pointless semantics here. I'm just
> waiting for you to characterise what things are acceptable to put in
> compiler switches, and what things not.
>
> --
> Lucian

Command line switches are usually used to choose between options. Do I
want debug assertions enabled, or do I want the code optimized for
speed/space/etc? Do I want the code to behave in a thread safe manner,
or is that unnecessary overhead?

For STRICT, there is no such choice. It is required that STRICT be
defined if you want windows.h to work with C++. It isn't an option, do
I want STRICT behavior or some non-STRICT behavior. It is simply a
requirement. Every time you include windows.h you must have STRICT defined.

Likewise with UNICODE. If your code calls MessageBox, and you pass it
L"Hello, world!", it will simply fail to compile if UNICODE isn't
defined. It isn't an option of whether or not you want to use UNICODE.
Technically, one could in fact write most code such that UNICODE
became an option (via macros like TCHAR and TEXT), but Alf has already
stated elsewhere that he is intentionally avoiding that.

Alan

Lucian Wischik

unread,
Apr 11, 2006, 1:45:32 AM4/11/06
to
"Alf P. Steinbach" <al...@start.no> wrote:
>shouldn't main's result type be configured via a macro? I don't
>think so. If someone did that, I'd think it was a joke. :-)

Like the old saying, "Every problem in computer science can be solved
by adding a layer of indirection".

Lucian's corollary: "Adding a layer of indirection always creates more
problems than it solves" !


>Also, if something is a fixed choice, should never vary (as with STRICT
>for C++), then I think it's a good idea to move that choice from the
>build configuration to the code, if possible, so that others won't have
>to engage in detective work to build the thing but can rely on defaults.

I guess we move to either Microsoft hegemony (every builds it from the
Visual Studio project file which includes the switch) or the Linux
approach (compilation is so tremendously varied that it's impossible
for a human to do; it can only be done with "./configure" and switches
centralised in a makefile).

--
Lucian

Lucian Wischik

unread,
Apr 11, 2006, 3:16:12 AM4/11/06
to
Lucian Wischik <lu...@wischik.com> wrote:
>I specifically think it's a bad idea to put these defines in a header.
>(1) it leads to you doing all those tests for whether something's
>already defined or not, (2) it's possible to forget it in one of your
>modules.

Actually, in retrospect, that's missing the point. The chief reason I
like to put these in compile-time switches rather than source code is
because they're framework, irritating setup and configuration, they're
not the actual *code*. I guess I just like to see source code that has
the algorithms it's supposed to implement and as little of the
supporting stuff as possible.

--
Lucian

0 new messages