home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 31
/
CDASC_31_1996_juillet_aout.iso
/
vrac
/
wdj0796.zip
/
SDKANN.ZIP
/
SDKANN.TXT
< prev
Wrap
Text File
|
1996-05-08
|
91KB
|
2,799 lines
Please send us your annotations! Just email them to
70302.2566@compuserve.com and indicate the topic and
the help file that your annotation refers to. Help
us build the SDK annotation database!
5/8/96 NOTE:
The AnnTater utility mentioned below has been mutated
to work with the InfoViewer that is integrated in
the Visual C++ IDE. Instead of running anntater.exe,
run mstater.exe if you want to annotate the IDE
InfoViewer (rather than any .hlp files you may have).
Let me know if you have problems.
12/1/95 NOTE:
The WDJ annotation package now includes anntater.exe.
AnnTater contains all of our annotations and you can use it
to automatically place our annotations in your help file.
Although I've tried to test this software in a variety of
situations, USE IT AT YOUR OWN RISK. If you have
annotations of your own, you may want to back up your .ann
file before running AnnTater. To use AnnTater, follow
these steps. If you don't have annotations of your own, the
easiest route is to delete your .ann file each time you run
anntater.exe on a new installment of our annotations.
1) invoke anntater.exe
2) select a type of help file (Windows 3.1 API or Win32 API)
3) if necessary, press the Locate button to specify the
path where this helpfile exists
4) select one or more annotations that you want to install
5) press the Copy button
6) press Done
Note that the program displays a checkmark beside
each annotation that it believes it has successfully
installed during the current session.
----------
This is the Windows Developer's Journal SDK Annotation File, a
growing collection of useful annotations for the standard online Windows
API help file, win31wh.hlp, which is included with every Windows C++
compiler. You can either cut and paste these annotations into your own
SDK help file (use ALT-E-A to create a help topic annotation), or you
can use anntater.exe to install them automatically for you.
If you have a useful annotation you would like to submit to our
collection, send it to:
70302.2566@compuserve.com
If we use your annotation, you will be listed as the
contributor. Our thanks to the dozens of readers whose
contributions help us continue to build this database of
useful information for the Windows programming community.
Windows Developer's Journal
"The Magazine for Windows Developers"
Windows Developer's Journal is the monthly publication for
advanced Windows programmers. We cover a variety of topics
such as Windows 95 programming, NT programming device
drivers, undocumented functions, compiler bugs, operating
system bugs, graphics, MFC, multimedia, communications, and
so on -- usually in the form of reusable code that you can
use immediately (most of our code has been compiled with
both Borland and Microsoft C/C++ compilers). In addition,
each month contains regular features like these:
* SDK Annotations
(they appear in the magazine before they appear in this file)
* Bug++ of the Month
(nasty bugs in popular C++ compilers)
* Tech Tips
(user-submitted tips and techniques)
* Books in Brief
(quick looks at recent books)
* Understanding NT
(covers NT-specific programming issues)
and more. WDJ costs $34.99/year in the US, $45/year Canada/Mexico, or
$64/year overseas. To order a subscription, contact
Miller Freeman
P.O. Box 56565
Boulder, CO 80322-6565
(800) 365-1425
(303) 678-0439
wdsub@rdpub.com
To subscribe by email or fax, include your name, address,
phone number, MasterCard or Visa number, and expiration
date. From CompuServe, that email address would be
something like this:
>INTERNET:wdsub@rdpub.com
------------------------------------------------------------
WDJ SDK Annotation #1
TYPE: Win3.1
TOPIC: Dialog Boxes
KEYWORD: Dialog Boxes
If a listbox is the first control in a dialog's tab order
and the dialog box was not created with the WS_VISIBLE
style, the listbox does not correctly draw itself with the
focus.
Reference: p35, March 1993 Windows/DOS Developer's Journal.
------------------------------------------------------------
WDJ SDK Annotation #2
TYPE: Win3.1
TOPIC: Property Lists
KEYWORD: Property Lists
The oft-quoted maxim that using window properties is slower
than using class or window extra bytes (via
GetWindowWord()/SetWindowWord()) is totally false if you use
a global atom rather than a string to name the property.
Properties were about 20% slower than window words under
Windows 3.0, but under Windows 3.1 GetProp() is about 300%
faster than GetWindowWord().
Reference: p 49, March 1993 Windows/DOS Developer's Journal.
------------------------------------------------------------
WDJ SDK Annotation #3
TYPE: Win3.1
TOPIC: WM_MOUSEMOVE (2.x)
KEYWORD: WM_MOUSEMOVE
The documentation incorrectly states that the x and y
arguments are in screen coordinates. They are in client
coordinates.
------------------------------------------------------------
WDJ SDK Annotation #4 (revised)
TYPE: Win3.1
TOPIC: SetWindowsHookEx (3.1)
KEYWORD: SetWindowsHookEx
SetWindowsHookEx() has a bug: using it to install a
task-specific hook can cause various failures. The
workaround is to pass it a module handle rather than an
instance handle. You can obtain a module handle from
GetModuleHandle(). If you only have the current instance
handle and not the name of the module, use the following
undocumented hack under Windows 3.1:
GetModuleHandle(MAKELP(0,hInstance));
If you #include <windowsx.h>, you can instead use the macro
GetInstanceModule(hInstance). Under Windows NT, just pass a
NULL to obtain the handle of the current process. Note that
the MSDN News article on this subject has the arguments to
MAKELP() backwards.
Reference: MSDN News #1, 1993
Revised by: Tom Nolan
------------------------------------------------------------
WDJ SDK Annotation #5
TYPE: Win3.1
TOPIC: CS_BYTEALIGNWINDOW 0x2000
KEYWORD: CS_BYTEALIGNWINDOW
The documentation makes it sound like this style bit is the
one you want for efficient bitblts. In fact, most of your
bitblts will be to the client area of the window, not the
non-client area, so CS_BYTEALIGNCLIENT is the style bit you
should set if you are concerned about bitblt operation
efficiency. Unaligned windows are slower at VGA resolution,
but typically not an issue with higher resolution
adapters (such as 256-color SVGA).
Reference: p65, December 1993 Windows/DOS Developer's Journal.
------------------------------------------------------------
WDJ SDK Annotation #6
TYPE: Win3.1
TOPIC: CODE Module Definition Statement
KEYWORD: CODE Module Definition Statement
The documentation for the FIXED attribute is incorrect.
Under Windows 3.1, if you mark code or data segments in your
.exe FIXED, the loader ignores that attribute -- the
segments will be moveable. If you mark code or data
segments in your .dll FIXED, however, the loader will make
them fixed and will page lock them as well. Due to the
implementation of GlobalPageLock(), that can result in your
segments using up precious DOS memory, eventually preventing
Windows from spawning new applications (since each new
application needs at least 512 bytes of DOS memory for a
task database entry). The October 1994 Windows
Developer's Journal provides code to allocate fixed memory
without using up precious conventional memory.
------------------------------------------------------------
WDJ SDK Annotation #7
TYPE: Win3.1
TOPIC: WS_EX_TRANSPARENT 0x00000020L
KEYWORD: WS_EX_TRANSPARENT
Note that this bit does not really create transparent
windows. If you create a window with this style, it is true
that the windows below it will show through as its
background. However, if you then move your new window, it
will have the same background as it did in its original
position -- blotting out whatever it is covering in its new
position.
------------------------------------------------------------
WDJ SDK Annotation #8
TYPE: Win3.1
TOPIC: WM_NCHITTEST (2.x)
KEYWORD: WM_NCHITTEST
You can process this message to allow the user to drag a
window that does not have a title bar. When you receive a
WM_NCHITTEST message and the mouse is in your client area
(or whatever conditions you want to start the drag), just
return HTCAPTION rather than passing the message on to
DefWindowProc().
Reference: p 37, March 1993 Windows/DOS Developer's Journal.
------------------------------------------------------------
WDJ SDK Annotation #9
TYPE: Win3.1
TOPIC: WM_TIMER (2.x)
KEYWORD: WM_TIMER
Although it sounds odd, you can use a WM_TIMER message as a
way to kill another application, if you can obtain the
handle of the main of the application you want to kill.
Create a timer callback function that does nothing but pass
its first argument (window handle) to DestroyWindow(). Then
use PostMessage() to post (to the other app's main window) a
WM_TIMER message that points to your callback function.
Your timer callback will get executed in the context of the
target application.
Reference: p 64, September 1992 Windows/DOS Developer's Journal.
------------------------------------------------------------
WDJ SDK Annotation #10
TYPE: Win3.1
TOPIC: MemoryWrite (3.1)
KEYWORD: MemoryWrite
MemoryWrite() has a bug in it: it trashes the high 16 bits
of the EDI register (the 32-bit version of the DI register).
The workaround is to save the register before calling
MemoryWrite() and restore it afterward.
Reference: p. 71, April 1994 Windows/DOS Developer's Journal
------------------------------------------------------------
WDJ SDK Annotation #11
TYPE: Win3.1
TOPIC: EscapeCommFunction (2.x)
KEYWORD: EscapeCommFunction
The documentation omits one potential value for the
nFunction parameter, although it is defined in windows.h.
The name is GETBASEIRQ and it returns the base address of
the COM port in the lower word and the IRQ setting in the
high word. If the high word is -1 the port doesn't exist;
if it is 0, the comm driver does not support this escape
(which is the case, for example with some kinds of enhanced
serial boards).
Submitted by: Thomas Zeisluft
------------------------------------------------------------
WDJ SDK Annotation #12
TYPE: Win3.1
TOPIC: MessageBox (2.x)
KEYWORD: MessageBox
Do not call MessageBox() from within the LibMain() of an
implicitly-linked DLL. It will fail because the application
will not yet have a message queue at that point, and
MessageBox() (or anything else) cannot create its window
when the message queue does not yet exist. Once the
application executes its internal startup code and calls
InitApp(), then it has a message queue and can safely call
functions that create windows.
------------------------------------------------------------
WDJ SDK Annotation #13
TYPE: Win3.1
TOPIC: LB_ADDSTRING (2.x)
KEYWORD: LB_ADDSTRING
If you are changing the contents of a listbox (for example,
by adding or deleting multiple strings), you may want to
minimize screen redrawing and maximize speed by disabling
window redrawing during your operation. Follow these steps:
1) Send a WM_SETREDRAW with wParam equal to FALSE to the listbox.
2) Perform your adds or deletes.
3) Send a WM_SETREDRAW with wParam equal to TRUE to the listbox.
4) Use InvalidateRect() to force the listbox to redraw itself.
Revised by V. Ramachandran
------------------------------------------------------------
WDJ SDK Annotation #14
TYPE: Win3.1
TOPIC: RegisterWindowMessage (2.x)
KEYWORD: RegisterWindowMessage
Do you really need to register a private window message?
Probably not, if all you need is an intra-app message number
that does not conflict with any Windows message numbers.
Microsoft has revised its statement about what message
numbers are available for your private use. Microsoft now
guarantees that you can use message numbers 0x8000 through
0xBFFF and they will not conflict with any system messages.
They also claim the next SDK (Chicago?) will define WM_APP
equal to 0x8000 in windows.h.
Reference: Microsoft Knowledge Base article Q86835
------------------------------------------------------------
WDJ SDK Annotation #15
TYPE: Win3.1
TOPIC: WM_CHAR (2.x)
KEYWORD: WM_CHAR
The documentation incorrectly claims that wParam is the
virtual key code. In fact, it is the ASCII value of the key
pressed. For example, pressing the '$' (ASCII 0x5B) key
produces a wParam equal to 0x5B -- if you interpreted that
as a virtual key code, you would incorrectly believe that
the user had pressed VK_HOME!
Submitted by: Brent Rector
------------------------------------------------------------
WDJ SDK Annotation #16
TYPE: Win3.1
TOPIC: WinHelp (3.0)
KEYWORD: WinHelp
The documentation says that the return value is nonzero if
WinHelp() is successful. In fact, WinHelp() only returns
failure for systemic problems, like being unable to allocate
global memory, or being unable to spawn winhelp.exe. If
WinHelp() successfully passes your request to winhelp.exe,
it returns success, period. So, for example, if the named
help file is invalid, or you try to jump to a help topic
that does not exist, or any number of other logical errors,
WinHelp() still returns success.
------------------------------------------------------------
WDJ SDK Annotation #17
TYPE: Win3.1
TOPIC: WM_ENTERIDLE (2.x)
KEYWORD: WM_ENTERIDLE
The documentation says that this messsage gets sent to your
application's "main window". In fact, a dialog sends the
WM_ENTERIDLE message to its own parent window, which may or
may not happen to be your application's main window.
------------------------------------------------------------
WDJ SDK Annotation #18
TYPE: Win3.1
TOPIC: OPENFILENAME (3.1)
KEYWORD: OPENFILENAME
The documentation does not completely describe the behavior
when selecting multiple files. To allow the user to select
multiple files, you turn on the flag OFN_ALLOWMULTISELECT.
If you do that and call GetOpenFileName(), and if the user then
selects multiple files, then GetOpenFileName() will copy (into
lpstrFile) the path, followed by a space, followed by
space-separated filenames. For example, if the user
selected files "fred.1" and "fred.2" from directory
"c:\test", lpstrFile would then point to the following
string:
"c:\test fred.1 fred.2"
However, the documentation does not point out that if the
user selects only one file, then the path is not kept
separate from the filename. Using the previous example, if
the user selected only file "fred.1", then lpstrFile would
point to this:
"c:\test\fred.1"
Submitted by Julian Templeman
------------------------------------------------------------
WDJ SDK Annotation #19
TYPE: Win3.1
TOPIC: CreateRoundRectRgn (3.0)
KEYWORD: CreateRoundRectRgn
This function has a bug. It will produce a GP fault if the
region rectangle is empty (either nLeftRect equals
nRightRect, or nBottomRect equals nTopRect). About the only
workaround is to create a wrapper function that first checks
whether the rectangle is empty.
Reference: p67, June 1994 Windows/DOS Developer's Journal^
Submitted by Chris Mason
------------------------------------------------------------
WDJ SDK Annotation #20
TYPE: Win3.1
TOPIC: EnableMenuItem (2.x)
KEYWORD: EnableMenuItem
When you are making changes to a window menu, the menu bar
is not immediately updated. To force those changes (such as
enabling/disabling menu items) to be visible right away,
make sure you call DrawMenuBar().
------------------------------------------------------------
WDJ SDK Annotation #21
TYPE: Win3.1
TOPIC: DrawText (2.x)
KEYWORD: DrawText
DrawText() has an off-by-one error that can result in a GP
fault. The bug is evoked when you use pass an explicit
string length instead of NULL-terminating the text string.
The bug is not evoked if you use the DT_NOPREFIX flag, or if
you NULL-terminate the text string (the easiest workaround).
Reference: p53, August 1994 Windows/DOS Developer's Journal
------------------------------------------------------------
WDJ SDK Annotation #22
TYPE: Win3.1
TOPIC: WM_MEASUREITEM (3.0)
KEYWORD: WM_MEASUREITEM
Windows supports owner-draw menus, but only popup owner-draw
menus work correctly. If you try to create an owner-draw
menubar for a window, Windows will not send you the
WM_MEASUREITEM message as it should.
Reference: Microsoft Knowledge Base article Q69969
------------------------------------------------------------
WDJ SDK Annotation #23
TYPE: Win3.1
TOPIC: WINDOWPOS (3.1)
KEYWORD: WINDOWPOS
The documentation says that y is "the position of the right
edge of the window". It is, of course, the position of the
top edge of the window.
------------------------------------------------------------
WDJ SDK Annotation #24
TYPE: Win3.1
TOPIC: Shell Dynamic-Data Exchange Interface Overview (3.1)
KEYWORD: Shell Dynamic-Data Exchange Interface Overview
The documentation says you can use DDE to get a list of
Program Manager groups by "issuing a request for the Group
item." In fact, that is not the correct item name -- you
must use 'Groups', not 'Group'.
------------------------------------------------------------
WDJ SDK Annotation #25
TYPE: Win3.1
TOPIC: TrackPopupMenu (3.0)
KEYWORD: TrackPopupMenu
The documentation incorrectly states that you can pass the
TPM_RIGHTBUTTON flag if you want the menu to respond to the
right (secondary) mouse button instead of the left (primary)
mouse button. In fact, passing TPM_RIGHTBUTTON causes the
menu to respond to the right mouse button as well as the
left. There is apparently no combination of bits that cause
the menu to respond only to the right mouse button.
------------------------------------------------------------
WDJ SDK Annotation #26
TYPE: Win3.1
TOPIC: SetDlgItemText (2.x)
KEYWORD: SetDlgItemText
There is a bug in Windows that keeps SetWindowText() and
SetDlgItemText() from working correctly when applied to an
edit control owned by another application. Rather than
sending a WM_SETTEXT to the edit control as they should,
these functions directly tinker with the target control's
internal window structure to change its title. The bug,
then, is twofold:
a) The target window is never notified that it
needs to repaint.
b) An edit control ignores its title, so changing
its title does not affect the text it contains.
The workaround is to use SendMessage() or PostMessage() to
deliver a WM_SETTEXT to the target window. If you use
PostMessage(), make sure you pass a string pointer that is
somehow guaranteed to still be valid whenever the target
application gets around to fetching and processing the
message.
Reference: p. 71, September 1993 Windows/DOS Developer's Journal
------------------------------------------------------------
WDJ SDK Annotation #27
TYPE: Win3.1
TOPIC: GetMenuItemID (2.x)
KEYWORD: GetMenuItemID
The documentation says that this function returns 0 if the
specified menu item is a separator. In fact, although the
resource compiler implicitly assigns separators an ID of 0,
you can assign them any 16-bit ID you like (with
ModifyMenu(), InsertMenu(), etc.) and this function will
return the correct ID, not just zero.
------------------------------------------------------------
WDJ SDK Annotation #28
TYPE: Win3.1
TOPIC: GetMetaFile (2.x)
KEYWORD: GetMetaFile
Most programs that write a "Windows metafile" to disk use a
newer file format that this function does not understand.
Most programs read and write "placeable" metafiles, a
metafile with a 22-byte header that contains a minimum
bounding rectangle for the figure. If you want to read in a
metafile that may have been written by another application,
you should open the file yourself and check the header to
see if it is a placeable metafile. See the SDK
documentation for a description of "placeable Windows
metafiles".
Reference: p. 43, November 1994 Windows/DOS Developer's Journal
------------------------------------------------------------
WDJ SDK Annotation #29
TYPE: Win3.1
TOPIC: WritePrivateProfileString (3.0)
KEYWORD: WritePrivateProfileString
The documentation for WritePrivateProfileString() and the
prototypes in windows.h, indicate that all strings passed in
are LPCSTR (32-bit pointer to unmodifiable character
string). However, sometimes this function writes on your
input string anyway! For one example, if you pass in the
string
"Hello World "
the function will remove the trailing spaces by writing a
NULL byte after the 'd'. If you were passing in a constant
string that resided in a code segment, this aberrant
behavior could result in a GP fault. This function
absolutely should not modify a string declared as LPCSTR,
but since it does, beware!
Submitted by Charles Leamon
------------------------------------------------------------
WDJ SDK Annotation #30
TYPE: Win3.1
TOPIC: GetMenuState (2.x)
KEYWORD: GetMenuState
In addition to the bits noted in the documentation, this
function also correctly returns MF_POPUP for a submenu.
Oddly, if you located the popup by position, the
MF_BYPOSITION flag will also be set in the returned flags,
although it is not on when used to locate normal menu items.
Note that some of these flags equate to zero, so you cannot
just AND them with the returned flags to see if they are on.
Here are the flags that equate to zero, along with the
expression you can use to infer their presence:
Zero Flag Expression to test for flag
============== =================================
MF_ENABLED !(Flag&~(MF_DISABLED|MF_GRAYED))
MF_UNCHECKED !(Flag&~MF_CHECKED)
MF_STRING !(Flag&~(MF_BITMAP|MF_OWNERDRAW))
------------------------------------------------------------
WDJ SDK Annotation #31
TYPE: Win3.1
TOPIC: GetWindowPlacement (3.1)
KEYWORD: GetWindowPlacement
From the documentation, you might think the following code
would work:
WINDOWPLACEMENT Info;
GetWindowPlacement(hWnd, &Info);
In fact, it won't. You must remember to initialize the
"length" field of the structure before calling this
function. The following code works:
WINDOWPLACEMENT Info;
Info.length = sizeof(Info);
GetWindowPlacement(hWnd, &Info);
Submitted by Pete Davis
------------------------------------------------------------
WDJ SDK Annotation #32
TYPE: Win3.1
TOPIC: CreateCompatibleBitmap (2.x)
KEYWORD: CreateCompatibleBitmap
The description of height and width parameters states that
these values are in bits, when actually they are in pixels.
Submitted by Charles Leamon
------------------------------------------------------------
WDJ SDK Annotation #33
TYPE: Win3.1
TOPIC: LoadCursor (2.x)
KEYWORD: LoadCursor
The documentation says that you should call DestroyCursor()
for cursors loaded via LoadCursor(). That is wrong -- you
should only call DestroyCursor() for cursors created with
CreateCursor().
Submitted by Charles Leamon^
Reference: Microsoft Knowledge Base article Q84779
------------------------------------------------------------
WDJ SDK Annotation #34
TYPE: Win3.1
TOPIC: lstrcpyn (3.1)
KEYWORD: lstrcpyn
The documentation for lstrcpyn() states that the last
parameter (cChars) is the number of characters to be copied,
when in fact the number of characters will be cChars-1.
That's convenient, but it's not what it says and it's
inconsistent with the standard ANSI C run-time function
strncpy(), which does copy the specified count. In other
words, unlike strncpy(), this function always
NULL-terminates the destination string.
Submitted by Charles Leamon
------------------------------------------------------------
(Note, this annotation proved to be incorrect and therefore does not
appear in the .ann files anymore.)
WDJ SDK Annotation #35
TYPE: Win3.1
TOPIC: ExitWindows (3.0)
KEYWORD: ExitWindows
In order for the EW_RESTARTWINDOWS feature to work,
ExitWindows() apparently must be able to locate WIN.COM.
Otherwise, calling ExitWindows() just exits Windows without
restarting. ExitWindows() doesn't seem to be very smart
about finding WIN.COM; having \WINDOWS on the DOS path
doesn't seem to do it, and it apparently doesn't search for
\WINDOWS on its own. The application using ExitWindows() in
this fashion should therefore either reside in the \WINDOWS
directory, or should change its current directory into the
\WINDOWS directory before calling ExitWindows() with
EW_RESTARTWINDOWS. Note that the user may have installed
Windows in a directory other than \WINDOWS, so you may want
to call GetWindowsDirectory() first.
Submitted by Stephen Posey
------------------------------------------------------------
WDJ SDK Annotation #36
TYPE: Win3.1
TOPIC: ExitWindows (3.0)
KEYWORD: ExitWindows
The documentation is incomplete. To just terminate Windows
and return control to DOS, pass a zero in the dwReturnCode
parameter.
Submitted by Charles Leamon^
Reference: Microsoft Knowledge Base article Q100359
------------------------------------------------------------
WDJ SDK Annotation #37
TYPE: Win3.1
TOPIC: OpenFile (2.x)
KEYWORD: OpenFile
WDJ SDK Annotation #37
The descriptions for OF_CANCEL and OF_PROMPT are incorrect.
OF_CANCEL does not add a cancel button to the 'File not
found' (OF_PROMPT) dialog. Even if it did, how would the
caller know the user pressed the cancel button (only one
error return is defined for OpenFile())? The OF_PROMPT
dialog does not prompt the user to insert a diskette into
drive A:
Submitted by Charles Leamon
------------------------------------------------------------
WDJ SDK Annotation #38
TYPE: Win3.1
TOPIC: WM_NCHITTEST (2.x)
KEYWORD: WM_NCHITTEST
The documentation claims that this message is sent to the
window that used SetCapture() to capture mouse input. That
is totally false. The window whose handle is passed to
SetCapture() will never receive any WM_NCHITTEST messages
(no matter where you move the moust) while the mouse is
captured.
Submitted by V. Ramachandran
------------------------------------------------------------
WDJ SDK Annotation #39
TYPE: Win3.1
TOPIC: TabbedTextOut (3.0)
KEYWORD: TabbedTextOut
The documentation claims that the tab stops are in device
units (pixels), but that is not true. The tab stops are
treated as logical units, not device units.
Submitted by Dan Miser^
Reference: Microsoft Knowledge Base article Q113253
------------------------------------------------------------
WDJ SDK Annotation #40
TYPE: Win3.1
TOPIC: LoadIcon (2.x)
KEYWORD: LoadIcon
The documentation says that you should call DestroyIcon()
for cursors loaded via LoadIcon(). That is wrong -- you
should only call DestroyIcon() for icons created with
CreateIcon().
Submitted by Charles Leamon^
Reference: Microsoft Knowledge Base article Q84779
------------------------------------------------------------
WDJ SDK Annotation #41
TYPE: Win3.1
TOPIC: COMPAREITEMSTRUCT (3.0)
KEYWORD: COMPAREITEMSTRUCT
Note that Windows has to send a WM_COMPAREITEM message when
a new item is added to the list, in order to determine its
correct position. That means it does not know the position
of the new item yet, so (contrary to the documentation) the
itemID2 field in this structure will be -1 -- do not assume
it will be a legal index value.
Submitted by V. Ramachandran
------------------------------------------------------------
WDJ SDK Annotation #42
TYPE: Win3.1
TOPIC: GetProcAddress (2.x)
KEYWORD: GetProcAddress
In attempting to locate the named function in the target
module, GetProcAddress() converts the function name to
uppercase and then performs a case-sensitive search. That
means that GetProcAddress() cannot locate functions exported
with names containing lowercase characters. Normally,
that's not a problem, as the __pascal calling sequence
forces uppercase names. However, depending on the compiler
and linker tools and options you use, it is possible to
export __cdecl calling sequence functions with lowercase
characters, resulting in a function that GetProcAddress()
cannot locate.
Submitted by Keith Bluestone
------------------------------------------------------------
WDJ SDK Annotation #43
TYPE: Win3.1
TOPIC: SetScrollRange (2.x)
KEYWORD: SetScrollRange
The documentation says you can use this function to hide or
show standard scroll bars, but does not tell you how!
Basically, if you specify the same value for both the
minimum (nMin) and maximum (nMax) scrolling positions, the
function will hide the scroll bar. If the two positions are
not equal, the function will display the scroll bar.
Submitted by Paul Bonneau
------------------------------------------------------------
WDJ SDK Annotation #44
TYPE: Win3.1
TOPIC: LoadLibrary (2.x)
KEYWORD: LoadLibrary
If LoadLibrary() cannot find the library, it may display an
error message to the user, depending upon the state of
Windows' "error mode". If you want to handle that case
yourself and make sure Windows does not display the error
message, see the documentation for the function
SetErrorMode(). For example, the following code attempts to
load the library ctl3d.dll, but does not emit an error
message if it is not found.
HINSTANCE Ctl3d;^
UINT OldFlag = SetErrorMode(SEM_NOOPENFILEERRORBOX);^
Ctl3d = LoadLibrary("ctl3d.dll");^
SetErrorMode(OldFlag); // restore previous mode^
if(Ctl3d <= HINSTANCE_ERROR)^
// LoadLibrary() failed for some reason^
------------------------------------------------------------
WDJ SDK Annotation #45
TYPE: Win3.1
TOPIC: LoadLibrary (2.x)
KEYWORD: LoadLibrary
The documentation claims this function returns an error code
of 0 if "System was out of memory, executable file was
corrupt, or relocations were invalid". However, if a
library's LibMain() function returns 0 (signifying some
logical error during initialization), LoadLibrary() also
returns 0. Therefore, do not assume that a 0 error code
means the system was out of memory or that the module was
corrupt in some way.
------------------------------------------------------------
WDJ SDK Annotation #46
TYPE: Win3.1
TOPIC: DdeClientTransaction (3.1)
KEYWORD: DdeClientTransaction
The documentation does not say so, but the cbData argument
(length of data) must include the NULL byte if the data is a
string. In other words, if lpvData is a string, cbData must
be set to strlen(lpvData)+1. Otherwise, bad things may
happen in DDEML when you perform an XTYP_POKE or
XTYP_EXECUTE.
Submitted by Mark Reha^
Reference: Microsoft Knowledge Base article Q107387.
------------------------------------------------------------
WDJ SDK Annotation #47
TYPE: Win3.1
TOPIC: WinHelp (3.0)
KEYWORD: WinHelp
The WinHelp() API function normally allows one to execute
macros, jumps, popups, and so on. However, if WinHelp was
started with WinExec() (i.e. from Program Manager or File
Manager) instead of the WinHelp() API function, you will not
be able to execute macros or jumps on that help file without
starting up a second instance of the help file using the
WinHelp() API function.
There is one way around this. You can create a DLL with an
LDLLHandler that gets the callback address for the FAPI()
function from WinHelp. FAPI() has the same parameters as
the WinHelp() API function except that the first parameters
(HWND) is not in FAPI() (so FAPI() only has 3 parameters).
The FAPI() function will allow you to execute macros, jumps,
popups, etc regardless of how WinHelp was launched. For
more information, get the Windows Help Authors Guide from
the MSDN CD-ROM or see Jim Mischel's book "The Developer's
Guide to WINHELP.EXE".
Submitted by Pete Davis
------------------------------------------------------------
WDJ SDK Annotation #48
TYPE: Win3.1
TOPIC: _fpmath (2.x)
KEYWORD: _fpmath
When setting the handler for coprocessor error exceptions
(function 3), the documentation incorrectly says you should
place the address of your exception handler in DS:AX. The
correct registers to use for this 32-bit address are DX:AX.
Submitted by Manfred Keul
------------------------------------------------------------
WDJ SDK Annotation #49
TYPE: Win3.1
TOPIC: VerQueryValue (3.1)
KEYWORD: VerQueryValue
Amazingly, even though the second parameter to this function
is declared const (LPCSTR), VerQueryValue() modifies that
string anyway! Apparently the code replaces a '\' in your
string with a NULL byte temporarily and then puts it back.
This is a bug. For example, suppose you use a compiler
option that places constant strings in read-only code
segments (for Microsoft, "/Gf"; for Borland "-dc"). In that
case, passing such a constant string as the second argument
to this function results in a GP fault.
Submitted by David Lowndes
------------------------------------------------------------
WDJ SDK Annotation #50
TYPE: Win3.1
TOPIC: GetProfileString (2.x)
KEYWORD: GetProfileString
This applies to both GetProfileString() and
GetPrivateProfileString(). If the default value for these
functions contains trailing blanks and the default value is
used because the key did not appear in the INI file, Windows
will null-terminate the string (even though it is declared
const!) at the first trailing blank. If that string is a
literal string and the code is compiled with some
optimizations then the string will end up in a code segment,
resulting in a GPF when the API function attempts to modify
it.
GetProfileString() and GetPrivateProfileString() also strip
out any leading spaces, and any leading and trailing quotes
(single or double quotes).
Submitted by Michael E. Kropp.^
Revised by Kai Riihioja
------------------------------------------------------------
WDJ SDK Annotation #50
TYPE: Win3.1
TOPIC: GetPrivateProfileString (2.x)
KEYWORD: GetPrivateProfileString
This applies to both GetProfileString() and
GetPrivateProfileString(). If the default value for these
functions contains trailing blanks and the default value is
used because the key did not appear in the INI file, Windows
will null-terminate the string (even though it is declared
const!) at the first trailing blank. If that string is a
literal string and the code is compiled with some
optimizations then the string will end up in a code segment,
resulting in a GPF when the API function attempts to modify
it.
GetProfileString() and GetPrivateProfileString() also strip
out any leading spaces, and any leading and trailing quotes
(single or double quotes).
Submitted by Michael E. Kropp.^
Revised by Kai Riihioja
------------------------------------------------------------
WDJ SDK Annotation #51
TYPE: Win3.1
TOPIC: GetTickCount (2.x)
KEYWORD: GetTickCount
GetTickCount() may return units of milliseconds, but its
resolution is much worse than one millisecond under Windows
3.1. For more accurate timings, call the function
timeGetTime(), which is defined in mmsystem.h.
------------------------------------------------------------
WDJ SDK Annotation #52
TYPE: Win3.1
TOPIC: GetWinFlags (3.0)
KEYWORD: GetWinFlags
GetWinFlags() can also tell you if your 16-bit Windows 3.1
application is running under Windows NT:
if(GetWinFlags() & 0x04000)^
// then we are running under Windows NT^
Submitted by Paula Tomlinson.^
Reference: "The Ultimate Windows Version Detector",
Windows/DOS Developer's Journal, February 1995.
------------------------------------------------------------
WDJ SDK Annotation #53
TYPE: Win3.1
TOPIC: KillTimer (2.x)
KEYWORD: KillTimer
Under at least one condition, KillTimer() does not remove a
pending WM_TIMER message from the message queue as
documented. First, understand that Windows just sets a bit
when a timer fires; it does not generate a WM_TIMER message
at that time. A timer message is secretly added to your
input queue when you call GetMessage() or PeekMessage() and
a timer event is pending and no other messages are in the
queue.
If you are using a PeekMessage() call with the PM_NOREMOVE
flag and if the timer bit is on at that point, PeekMessage()
will place a WM_TIMER message in the queue, but won't remove
it. If you then call KillTimer(), it will ensure the timer
bit is off but won't remove the WM_TIMER message. The next
call to GetMessage() or PeekMessage() returns this WM_TIMER
message. One workaround is to use code like this to
terminate a timer:
KillTimer (hWnd, ID);^
if (LOWORD (GetQueueStatus (QS_TIMER)) & QS_TIMER)^
PeekMessage (&msg, hWnd, WM_TIMER, WM_TIMER, PM_REMOVE);^
Submitted by Mike Mast.
------------------------------------------------------------
WDJ SDK Annotation #54
TYPE: Win3.1
TOPIC: DEVMODE (3.0)
KEYWORD: DEVMODE
The documentation claims that DMCOLOR_COLOR is defined to be
1 and DMCOLOR_MONOCHROME is defined to be 2. In fact, if
you look in print.h you discover that the reverse is true.
Submitted by Bill Liu.
------------------------------------------------------------
WDJ SDK Annotation #55
TYPE: Win3.1
TOPIC: EN_CHANGE (2.x)
KEYWORD: EN_CHANGE
The documentation implies this notification only arises from
actions by the user. In fact, this notification also arises
from programmatic changes, such as from sending a WM_SETTEXT
message to the edit control, or using SetWindowText() (which
sends a WM_SETTEXT message). Not knowing this, you might
code an EN_CHANGE handler that attempts to modify the edit
control text, resulting in another EN_CHANGE notification --
an infinite loop!
Submitted by Scott Smith.
------------------------------------------------------------
WDJ SDK Annotation #56
TYPE: Win3.1
TOPIC: EnumFonts (2.x)
KEYWORD: EnumFonts
The 3.1 documentation for this function specifies that the
third argument is of type FONTENUMPROC. This was true in
previous versions, but in 3.1 this call is deprecated in
favour of the new EnumFontFamilies() API function. The
definition of the FONTENUMPROC type has been updated to take
a NEWTEXTMETRIC parameter, and therefore no longer quite
matches the prototype specified for EnumFonts. Microsoft
provids a new type, OLDFONTENUMPROC, which corresponds to
the STRICT definition of EnumFonts in windows.h, but this is
not reflected in the documentation. In other words, if you
compile with STRICT defined for Windows 3.1 and want to use
EnumFonts(), make sure the third parameter is of type
OLDFONTENUMPROC.
Submitted by David W. Gillett.
------------------------------------------------------------
WDJ SDK Annotation #57
TYPE: Win3.1
TOPIC: PtInRect (2.x)
KEYWORD: PtInRect
There is no mention of this, but the rectangle MUST be
normailized before this function is called. In other words,
you have to make sure that lprc->right is greater than
lprc->left, and that lrpc->bottom is greater than lrpc->top.
Otherwise, the point will never be considered inside of the
rectangle. By contrast, the function RectInRegion() does
accept and correctly handle all rectangles, whether
normalized or not.
Submitted by Peter Ritchie.
------------------------------------------------------------
WDJ SDK Annotation #58
TYPE: Win3.1
TOPIC: SetTimer (2.x)
KEYWORD: SetTimer
The documentation makes it sound like Windows either posts a
message (if you supply no callback function) or else calls
your callback function directly when the timer expires. In
fact, when the timer fires, Windows sets a bit in your
message queue which gets transformed into a WM_TIMER message
by either GetMessage() or PeekMessage() when they find no
other messages in the input queue. The WM_TIMER message
contains the address of your callback function (if any),
which will be called by DefWindowProc() after the message is
dispatched to your window. The key point here is that the
timers created by SetTimer() are always message based
(Windows does not call your timer procedure asynchronously)
and of a lower priority than any other Windows message.
Submitted by Alan M. Carroll.
------------------------------------------------------------
WDJ SDK Annotation #59
TYPE: Win3.1
TOPIC: lstrcpy (2.x)
KEYWORD: lstrcpy
Believe it or not, this function (and apparently other
similar functions) examine the limit of the selector of the
output string, and even attempt to silently recover if the
operation causes a GP fault. As a consequence, you should
not count on this function being a real speed demon.
Submitted by Vivek Venugopalan
------------------------------------------------------------
WDJ SDK Annotation #60
TYPE: Win3.1
TOPIC: GetModuleFileName (2.x)
KEYWORD: GetModuleFileName
Windows 3.1 has a bug that causes this function to sometimes
return relative paths instead of absolute (fully qualified)
paths.This error occurs if a relative path is specified in
the PATH variable, and the DLL is implicitly loaded from
this directory. For example, if the PATH variable is:
PATH=C:\DOS;D:.;C:\UTILS
and an application running from any other directory but
"D:.", loads a DLL (test.dll) in "D:." implicitly (since it
is in the path), then a call to GetModuleFileName() with the
DLL instance will return "D:.\test.dll".
Submitted by V. Ramachandran
Reference: MSKB PSS ID Number: Q85330.
------------------------------------------------------------
WDJ SDK Annotation #61
TYPE: Win3.1
TOPIC: CB_GETDROPPEDCONTROLRECT (3.1)
KEYWORD: CB_GETDROPPEDCONTROLRECT
The documentation claims that this function retrieves the
screen coordinates of the listbox portion of a combo box.
In fact, it retrieves the screen coordinates of the
rectangle that encloses the ENTIRE combo box in its
dropped-down state. That means the rectangle retrieved is
both bit taller and a bit wider than the rectangle that the
help file claims is returned.
Submitted by V. Ramachandran
------------------------------------------------------------
WDJ SDK Annotation #62
TYPE: Win3.1
TOPIC: NotifyUnRegister (3.1)
KEYWORD: NotifyUnRegister
As the documentation says, you can set the htask argument to
NULL to refer to the current task. This is probably not a
good practice, however. If more than one application can
load your DLL, then there is typically some scenario under
which the task that you called NotifyRegister() for has died
before you call NotifyUnRegister(), in which case passing
NULL would refer to the wrong task. It's probably safer to
explicitly store that task that was passed to
NotifyRegister() and make sure you pass the same task to
NotifyUnregister().
Submitted by Paul Dolphin.
------------------------------------------------------------
WDJ SDK Annotation #63
TYPE: Win3.1
TOPIC: CreateCompatibleDC (2.x)
KEYWORD: CreateCompatibleDC
You might think from the name that this function returns a
device context whose attributes are the same as the source
device context. In fact, attributes such as the mapping
mode will be set to their defaults (e.g., the mapping mode
will always be MM_TEXT) in the returned device context, not
to the attribute values of the source device context.
Submitted by Stuart Patterson^
Reference: p. 624, "Programming Windows 3.1, 3rd Edition",
by Charles Petzold
------------------------------------------------------------
WDJ SDK Annotation #64
TYPE: Win3.1
TOPIC: Device Contexts
KEYWORD: Device Contexts
The help file says CreateCompatibleDC() creates a device
context that "has the same attributes" as the source device
context. In fact, the device context's attributes (such as
mapping mode) will have their default values, no matter what
value they had in the source device context.
Submitted by Stuart Patterson^
Reference: p. 624, "Programming Windows 3.1, 3rd Edition",
by Charles Petzold
------------------------------------------------------------
WDJ SDK Annotation #65
TYPE: Win3.1
TOPIC: UngetCommChar (2.x)
KEYWORD: UngetCommChar
Do not use this function under Windows 3.1 -- it causes lost
characters or even GP faults!
Submitted by Manfred Keul.^
Reference: Microsoft Knowledge Base article Q100183.
------------------------------------------------------------
WDJ SDK Annotation #66
TYPE: Win3.1
TOPIC: TabbedTextOut (3.0)
KEYWORD: TabbedTextOut
If a tab character is the last character in the string, then
all of the area to the next tab stop is filled with the
current background color. This may or may not be the
behavior you want in any given situation.
Submitted by Tim English.
------------------------------------------------------------
(Note: due to a bug in WinHelp, it is not possible to display
or annotate the GetRgnBox topic in the Visual C++ v1.5
version of the helpfile)
WDJ SDK Annotation #67
TYPE: Win3.1
TOPIC: GetRgnBox (3.0)
KEYWORD: GetRgnBox
The documentation claims GetRgnBox() returns COMPLEXREGION
when the region has overlapping borders. In fact,
GetRgnBox() apparently returns COMPLEXREGION if the region
is simply non-rectangular, whether overlapping borders are
involved or not.
Submitted by Jason Douglas.
------------------------------------------------------------
WDJ SDK Annotation #68
TYPE: Win3.1
TOPIC: DRAWITEMSTRUCT (3.0)
KEYWORD: DRAWITEMSTRUCT
The itemID field in this structure is set to a negative value
for an empty listbox or combobox. Watch out, though -- since
this field is defined to be unsigned (UINT), a statement like
this:
if(lpdis->itemID >= 0) // if listbox not empty^
// ... some code^
will always evaluate true. To check for an empty listbox or
combobox, either cast the field to int or check the high bit:
if( (int) lpdis->itemID >= 0) // this works correctly^
//... some code^
Submitted by Aaron O'Neil.
------------------------------------------------------------
WDJ SDK Annotation #69
TYPE: Win3.1
TOPIC: DDEDATA (2.x)
KEYWORD: DDEDATA
In this help topic, the description for the fResponse field
actually describes the fAckReq field, and vice versa.
Submitted by Sudhir Menon.^
Reference: Microsoft Knowledge Base article Q93372.
------------------------------------------------------------
WDJ SDK Annotation #70
TYPE: Win3.1
TOPIC: EnableCommNotification (3.1)
KEYWORD: EnableCommNotification
Due to bugs in Windows 3.1, you will probably want to always set
both cbWriteNotify and cbOutQueue to -1, thus disabling the
CN_TRANSMIT and CN_RECEIVE notifications. If you do not set
them to -1, spurious WM_COMMNOTIFY messages can be sent,
resulting in a system crash at higher baud rates.
Submitted by Manfred Keul.^
Reference: Microsoft Knowledge Base article Q101420.
------------------------------------------------------------
WDJ SDK Annotation #71
TYPE: Win3.1
TOPIC: GetMsgProc (3.1)
KEYWORD: GetMsgProc
The help file fails to mention that your hook function gets
called by PeekMessage(), not just by GetMessage(). The
documentation also contradicts itself, saying first that wParam
is undefined and later saying that wParam is NULL. The
Microsoft Knowledge Base, on the other hand, reveals that wParam
contains the PM_ flags that were used in the call to
PeekMessage(), so your message hook can, for example, determine
if the message was being removed or not with code like this:
if(wParam & PM_REMOVE)^
//... then message is being removed^
else^
//... message is not being removed^
Note that your hook may want to ignore the message if it is not
being removed, since your hook will get called again when the
same message is removed by some future call to GetMessage() or
PeekMessage().
Submitted by V. Ramachandran.^
Reference: Microsoft Knowledge Base article Q104068
------------------------------------------------------------
WDJ SDK Annotation #72
TYPE: Win3.1
TOPIC: GetInstanceData (2.x)
KEYWORD: GetInstanceData
Both the documentation and windows.h declare the second
parameter as a BYTE*. Unfortunately, that declaration is only
correct if you are using a memory model with near data (small or
medium memory models), and will be incorrect for large or huge
memory models. The correct declaration for this argument is
BYTE NEAR*.
Submitted by Martin Cooper.
------------------------------------------------------------
WDJ SDK Annotation #73
TYPE: Win3.1
TOPIC: MENUITEMTEMPLATE (3.0)
KEYWORD: MENUITEMTEMPLATE
Missing from the list of bits you can turn on in mtOption is
MF_END (0x0080), which indicates that the item terminates
the menu.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #74
TYPE: Win3.1
TOPIC: AddAtom (2.x)
KEYWORD: AddAtom
AddAtom() handles strings that begin with "#" specially:
it expects the string following the "#" to be a string
of digits, and returns an atom is value is the 16-bit
binary representation of that string of digits. Unfortunately,
if your first call to AddAtom() is with a string like "#nondigits",
it will produce a divide by zero fault. Two workarounds
are possible: either make sure your first call to AddAtom()
does not contain such a string, or call InitAtomTable()
before calling AddAtom() for the first time.
Submitted by V. Ramachandran.^
Reference: MSKB PSS ID Number: Q103036
------------------------------------------------------------
WDJ SDK Annotation #75
TYPE: Win3.1
TOPIC: DCB (2.x)
KEYWORD: DCB
When setting the BaudRate field, do not use the constant
CBR_14400; Windows 3.1's COMM.DRV has a bug that will produce
communications problems due to a bad table entry for that
constant. Instead, set BaudRate to the integer 14400 to
communicate at 14400 baud.
Submitted by Manfred Keul.^
Reference: Microsoft Knowledge Base article Q83232.
------------------------------------------------------------
WDJ SDK Annotation #76
TYPE: Win3.1
TOPIC: RegisterRoutine WinHelp macro
KEYWORD: RegisterRoutine WinHelp macro
The documentation does not reveal how to specify the return type
of the function. You do this by inserting a type-specifying
character followed by an equal sign in the third parameter
string. For example, to register FindWindow() (which takes
two far strings and returns a 16-bit unsigned integer), you
might use:
RR("USER", "FindWindow", "u=SS");
Note that if you do not specify a return type when you register
a function, you cannot use that function in an IfThen or
IfThenElse macro.
Submitted by Sudhir Menon.
------------------------------------------------------------
WDJ SDK Annotation #77
TYPE: Win3.1
TOPIC: RTF Tokens
KEYWORD: RTF Tokens
Strangely, the tokens "emc", "eml", and "emr" are
misspelled in the online help -- they should be
"ewc", "ewl", and "ewr", where the "ew" stands for
Embedded Window. Note that this are not really RTF
tokens, but literal text. The help compiler scans
for any text you have entered of the form "{ewx commands}"
in order to detect embedded window commands. Such text,
when translated by your word processor into RTF, looks
like this: "\{ewx commands\}".
Submitted by John Sawyer.
------------------------------------------------------------
WDJ SDK Annotation #78
TYPE: Win3.1
TOPIC: WM_ENTERIDLE (2.x)
KEYWORD: WM_ENTERIDLE
Note that you can elect to suppress the WM_ENTERIDLE
message for a particular modal dialog box by defining
it with the DS_NOIDLEMSG window style bit.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #79
TYPE: Win3.1
TOPIC: WM_SYSCOMMAND (2.x)
KEYWORD: WM_SYSCOMMAND
You can use this message with SC_MENUKEY to simulate the
user selecting a menu with an accelerator key. For example,
to simulate the user accessing the "File" menu, you might
use the following code:
PostMessage(hWnd, WM_SYSCOMMAND, SC_MENUKEY, MAKELPARAM('f',0));
Submitted by Jay Giganti.
------------------------------------------------------------
WDJ SDK Annotation #80
TYPE: Win3.1
TOPIC: wsprintf
KEYWORD: wsprintf
The documentation says the second parameter is an LPSTR,
but it is actually an LPCSTR (and so declared in windows.h),
so it's safe to use a string constant.
Submitted by: V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #81
TYPE: Win3.1
TOPIC: _lread (2.x)
KEYWORD: _lread
If you call _lread() to read a floppy when there is no
diskette in the drive, Windows puts up a system error
message box ("Cannot Read from Drive...") with Retry and
Cancel buttons. If the user presses the Cancel button,
_lread() returns a non-negative number, indicating success.
It should return HFILE_ERROR instead.
To avoid this error, call SetErrorMode(SEM_NOOPENFILEERRORBOX)
before calling _lread(), then it will correctly return -1 on
failure.
Submitted by: V. Ramachandran.^
Reference: MSDN PSS ID No. Q111587.
------------------------------------------------------------
WDJ SDK Annotation #82
TYPE: Win3.1
TOPIC: WM_COMPAREITEM (3.0)
KEYWORD: WM_COMPAREITEM
The documentation for WM_COMPAREITEM says that the parent of
owner-drawn listboxes with the LBS_SORT (or CBS_SORT) styles
will get this message in order to determine the relative
position. However, Windows will not send the WM_COMPAREITEM
message if the LBS_HASSTRINGS style bit is set, even if it
is an owner-drawn listbox with the LBS_SORT style. The same
is true for comboboxes.
Submitted by: V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #83
TYPE: Win3.1
TOPIC: DOCINFO (3.1)
KEYWORD: DOCINFO
The documentation fails to point out that lpszOutput is
limited to 32 characters, including the null terminating
byte. If you use a string longer than that, the trailing
characters will be ignored. For example, if you use a
string containing the too-long path:
c:\usr\ts\issues\pending\12345678\abcdefgh.out
the actual file that gets created will be:
c:\usr\ts\issues\pending\123456
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #84
TYPE: Win3.1
TOPIC: SetAbortProc function
KEYWORD: SetAbortProc
SetAbortProc() returns a negative value, which is documented
as indicating failure. However, the return value from
SetAbortProc does not indicate success or failure of the
function, so don't depend on the return value for anything.
Submitted by: V. Ramachandran.^
Reference: MSDN PSS ID No. Q109540.
------------------------------------------------------------
WDJ SDK Annotation #85
TYPE: Win3.1
TOPIC: BN_DISABLE (2.x)
KEYWORD: BN_DISABLE
The documentation claims the button sends this notification
whenever it gets disabled. In fact, Windows 3.1 buttons do
not appear to ever send this notification!
Submitted by: V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #86
TYPE: Win3.1
TOPIC: BN_DOUBLECLICKED (2.x)
KEYWORD: BN_DOUBLECLICKED
The documentation fails to point out that this notification
is only sent for buttons that have the BS_OWNERDRAW or
BS_RADIOBUTTON styles. No other types of buttons generate
this notification
Submitted by: V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #87
TYPE: Win3.1
TOPIC: WM_DROPFILES (3.1)
KEYWORD: WM_DROPFILES
Documentation for the undocumented handle has since been
published by Microsoft in Microsoft Systems Journal. This
handle points to a structure like this:
typedef struct {^
int wSize; // Number of bytes in this structure^
POINT ptMousePos; // Mouse position^
BOOL fInNonClientArea;// TRUE if mouse was in client area^
// Pathnames begin after structure each one zero-terminated^
// Zero-length pathname used to indicate the end^
} DROPFILESTRUCT, FAR *LPDROPFILESTRUCT;^
The Win32 version of this structure is slightly different. The
first field becomes a 4-byte rather than a 2-byte integer, and
the structure contains an additional BOOL field at the end that
is TRUE if the pathnames are in Unicode rather than ANSI
strings.
Submitted by V. Ramachandran.^
Reference: May/June 1992 Microsoft Systems Journal^
February 1994 Microsoft Systems Journal
------------------------------------------------------------
WDJ SDK Annotation #88
TYPE: Win3.1
TOPIC: List box messages
KEYWORD: List box messages
Internally, listboxes maintain two 32-bit DWORDs for each
listbox item. The first DWORD points to the text for the item
and the second DWORD contains whatever custom data you would
like; you can get it via LB_GETITEMDATA or set it via
LB_SETITEMDATA. Some messages refer to one or the other of
these DWORDs, depending on whether the LBS_HASSTRINGS style is
set:
Message LBS_HASSTRINGS? Refers to:^
==========================================================^
LB_ADDSTRING Yes text pointer (lParam)^
LB_ADDSTRING No custom data (lParam)^
LB_INSERTSTRING Yes text pointer (lParam)^
LB_INSERTSTRING No custom data (lParam)^
LB_GETTEXT Yes returns text pointer^
LB_GETTEXT No returns custom data^
LB_GETITEMDATA either returns custom data^
LB_SETITEMDATA either sets custom data (lParam)^
WM_DRAWITEM either custom data (in itemData field)^
In other words, if LBS_HASSTRINGS is not set, you cannot access
the normal text pointer -- all messages operate on the custom
data. But if LBS_HASSTRINGS is set, you can access both the
normal text as well as the extra DWORD of custom data.
Submitted by V. Ramachandran
------------------------------------------------------------
WDJ SDK Annotation #89
TYPE: Win3.1
TOPIC: SetTimer (2.x)
KEYWORD: SetTimer
Though the documentation does not mention this, you can
change the timer interval after you create the timer. If
you call SetTimer() with a window handle and a timer ID
equal to an existing timer and specify a different time
interval, SetTimer() updates the timer to the new time
interval.
Example:
Use the following line to set a timer to a particular time
interval.
UINT nTimerID = SetTimer (hWnd, TIMER_ID, TIME_INTERVAL, NULL)
Calling the following line will reset the timer to twice the
time interval.
nTimerID = SetTimer (hWnd, TIMER_ID, 2*TIME_INTERVAL, NULL)
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #90
TYPE: Win3.1
TOPIC: TranslateAccelerator (2.x)
KEYWORD: TranslateAccelerator
Contrary to the documentation, both WM_INITMENU and
WM_INITMENUPOPUP get sent, even if the menu item is disabled,
and even if the window is minimized and the keystroke matches no
menu items.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #91
TYPE: Win3.1
TOPIC: GetPrivateProfileInt (3.0)
KEYWORD: GetPrivateProfileInt
The documentation says you must use a positive integer
in the range 0 through 32,767 (0x7FFF) for the third
argument, which is the default value the function returns
if it cannot locate the desired entry in the .ini file.
In fact, you can pass any legal integer value for this
parameter -- it's just that since the function's return
type is defined to be UINT, you must cast the result to
int if you want to treat the result as a negative number.
For example, the following code works correctly, despite
what the documentation says:
int Val = (int)GetPrivateProfileInt(
"MyLib", "Debug", -1, "MyLib.ini");
if(Val == -1)
/* then no such entry found */
------------------------------------------------------------
WDJ SDK Annotation #92
TYPE: Win32
TOPIC: WM_NOTIFY
KEYWORD: WM_NOTIFY AND QuickInfo
If your dialog procedure handles a WM_NOTIFY that requires a
return value, note that you MUST both return a non-zero
value (to indicate to the dialog manager that you wish to
specify a return value for the message) AND store the
desired return value for the message in the window field
DWL_MSGRESULT. The standard Windows header file windowsx.h
provides a macro called SetDlgMsgResult() that makes this
easy:
#include <windowsx.h>
//...
case WM_NOTIFY :
{
NMHDR* Head = (NMHDR*)lParam;
if(Head->code == LVN_ENDLABELEDIT)
// allow user to edit listview labels
return SetDlgMsgResult(Dialog, WM_NOTIFY, TRUE);
}
------------------------------------------------------------
WDJ SDK Annotation #92
TYPE: Win32
TOPIC: LVN_ENDLABELEDIT
KEYWORD: LVN_ENDLABELEDIT AND QuickInfo
If your dialog procedure handles a WM_NOTIFY that requires a
return value (as this one does), note that you MUST both
return a non-zero value (to indicate to the dialog manager
that you wish to specify a return value for the message) AND
store the desired return value for the message in the window
field DWL_MSGRESULT. The standard Windows header file
windowsx.h provides a macro called SetDlgMsgResult() that
makes this easy:
#include <windowsx.h>
//...
case WM_NOTIFY :
{
NMHDR* Head = (NMHDR*)lParam;
if(Head->code == LVN_ENDLABELEDIT)
// allow user to edit listview labels
return SetDlgMsgResult(Dialog, WM_NOTIFY, TRUE);
}
------------------------------------------------------------
WDJ SDK Annotation #92
TYPE: Win32
TOPIC: LVN_BEGINLABELEDIT
KEYWORD: LVN_BEGINLABELEDIT AND QuickInfo
If your dialog procedure handles a WM_NOTIFY that requires a
return value (as this one does), note that you MUST both
return a non-zero value (to indicate to the dialog manager
that you wish to specify a return value for the message) AND
store the desired return value for the message in the window
field DWL_MSGRESULT. The standard Windows header file
windowsx.h provides a macro called SetDlgMsgResult() that
makes this easy:
#include <windowsx.h>
//...
case WM_NOTIFY :
{
NMHDR* Head = (NMHDR*)lParam;
if(Head->code == LVN_BEGINLABELEDIT)
// allow user to edit listview labels
return SetDlgMsgResult(Dialog, WM_NOTIFY, FALSE);
}
------------------------------------------------------------
WDJ SDK Annotation #93
TYPE: Win3.1
TOPIC: GetWindowText
KEYWORD: GetWindowText AND QuickInfo
GetWindowText() and GetDlgItemText() will not work when
applied to a standard edit control that belongs to another
application. The problem is that GetWindowText() and
GetDlgItemText() attempt to optimize by directly examining
the window caption of the target window. An edit control
stores an empty string in its caption, not the edit control
text, so this fails. You can avoid this bug by sending a
WM_GETTEXT explicitly:
HWND OtherEdit;
char Buffer[256];
SendMessage(OtherEdit, WM_GETTEXT,
sizeof(Buffer), (LPARAM)Buffer);
------------------------------------------------------------
WDJ SDK Annotation #93
TYPE: Win3.1
TOPIC: GetDlgItemText
KEYWORD: GetDlgItemText AND QuickInfo
GetWindowText() and GetDlgItemText() will not work when
applied to a standard edit control that belongs to another
application. The problem is that GetWindowText() and
GetDlgItemText() attempt to optimize by directly examining
the window caption of the target window. An edit control
stores an empty string in its caption, not the edit control
text, so this fails. You can avoid this bug by sending a
WM_GETTEXT explicitly:
HWND OtherEdit;
char Buffer[256];
SendMessage(OtherEdit, WM_GETTEXT,
sizeof(Buffer), (LPARAM)Buffer);
------------------------------------------------------------
WDJ SDK Annotation #94
TYPE: Win32
TOPIC: LVM_GETCOLUMNWIDTH
KEYWORD: LVM_GETCOLUMNWIDTH AND QuickInfo
The documentation claims that this message returns the
column width if successful, "or zero otherwise". In fact,
if you specify an invalid column number, this function
returns garbage. Therefore, you cannot use this message to
count the number of columns in a listview control. The
associated message, LVM_GETCOLUMN, does correctly return
zero when passed an invalid column number, so you can use
LVM_GETCOLUMN to determine the number of columns in a
listview control.
------------------------------------------------------------
WDJ SDK Annotation #95
TYPE: Win3.1
TOPIC: SystemParametersInfo (3.1)
KEYWORD: SystemParametersInfo AND QuickInfo
The documentation says that the screen saver time out
(SPI_GETSCREENSAVETIMEOUT) is specified in milliseconds. In
fact, the value returned is in seconds.
Submitted by: Carlton Guc
------------------------------------------------------------
WDJ SDK Annotation #96
TYPE: Win32
TOPIC: LVN_ENDLABELEDIT
KEYWORD: LVN_ENDLABELEDIT AND QuickInfo
The documentation claims that there is no return value for
this message. In fact, you should return FALSE if you want
to reject the user's editing, or TRUE if you want to allow
the changes to the listview item. If you are handling this
notification inside a dialog procedure, remember that you
must return a non-zero result AND store the message result
(either TRUE or FALSE) in DWL_MSGRESULT, using either
SetWindowLong() or the SetDlgMsgResult() macro (defined in
windowsx.h).
Submitted by: Poul A. Costinsky
------------------------------------------------------------
WDJ SDK Annotation #98
TYPE: Win32
TOPIC: RegSetValueEx
KEYWORD: RegSetValueEx AND QuickInfo
For string-based data types, such as REG_SZ, this function
behaves differently under Win95 and NT. Under Win95, if you
pass a value of "abcd" and a length of 4, the function will
actually append a null byte, and if you retrieve the value
later, you will find it has a length of 5. Under NT, this
function stores exactly what you tell it to store.
Submitted by Paula Tomlinson.
------------------------------------------------------------
WDJ SDK Annotation #97
TYPE: Win32
TOPIC: LVN_ITEMCHANGING
KEYWORD: LVN_ITEMCHANGING AND QuickInfo
The documentation incorrectly claims that you have to return
TRUE to allow the change, or FALSE to prevent it. In fact,
you have to return FALSE to allow the change or TRUE to
prevent it.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #99
TYPE: Win32
TOPIC: LV_DISPINFO
KEYWORD: LV_DISPINFO AND QuickInfo
The documentation says you can set the LVIF_DI_SETITEM flag
in the mask member to have Windows store the string and not
ask for it again. It fails to point out that this only
works for subitem 0 (the first column), so you would still
have to handle requests for the text of the other columns.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #100
TYPE: Win32
TOPIC: LVM_EDITLABEL
KEYWORD: LVM_EDITLABEL AND QuickInfo
Note that the listview control implements in-place editing
by creating an edit control on the fly. Unfortunately, it
assigns that edit control a child ID of IDOK, which means
that the parent of the listview control will receive edit
control notifications that it might not expect. For
example, if your listview control is in a dialog box, and
your dialog procedure contains code like this:
// inside WM_COMMAND handler...
if(ControlId == IDOK)
EndDialog(Dialog, TRUE);
Then it may terminate the dialog when the user starts
editing a listview item (since the transient edit control
will send notifications like EN_CHANGE, with a control ID of
IDOK). The above code should read:
// inside WM_COMMAND handler...
if(ControlId == IDOK && NotifyCode == BN_CLICKED)
EndDialog(Dialog, TRUE);
to be safe.
------------------------------------------------------------
WDJ SDK Annotation #101
TYPE: Win3.1
TOPIC: GetWindowTextLength (2.x)
KEYWORD: GetWindowTextLength AND QuickInfo
Due to a bug in Windows 3.1, both GetWindowTextLength() and
WM_GETTEXTLENGTH return -1 if you use it on a combobox of
style CBS_DROPDOWNLIST.
Submitted by Mircea Neacsu
------------------------------------------------------------
WDJ SDK Annotation #102
TYPE: Win32
TOPIC: LB_ADDSTRING
KEYWORD: LB_ADDSTRING AND QuickInfo
If you are planning to add a large number (more than 100) of
strings by calling LB_ADDSTRING, LB_INSERTSTRING, LB_DIR, or
LB_ADDFILE, consider first sending the new Win32 message
LB_INITSTORAGE to give the listbox a chance to preallocate
memory, thus speeding up the process.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #102
TYPE: Win32
TOPIC: LB_ADDSTRING
KEYWORD: LB_ADDSTRING AND QuickInfo
If you are planning to add a large number (more than 100) of
strings by calling LB_ADDSTRING, LB_INSERTSTRING, LB_DIR, or
LB_ADDFILE, consider first sending the new Win32 message
LB_INITSTORAGE to give the listbox a chance to preallocate
memory, thus speeding up the process.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #103
TYPE: Win32
TOPIC: LoadString
KEYWORD: LoadString AND QuickInfo
Even though resource strings are stored as Unicode for both
Win95 and NT programs, Win95 does not provide an
implementation of the Unicode version of LoadString()
(LoadStringW()). This usually trips up NT programmers who
want to create a single .exe for both operating systems and
yet still use Unicode under NT. In that case, you must at
runtime detect that you are running under Win95 and, in that
case, explicitly call LoadStringA(). Otherwise, if you have
compiled with _UNICODE defined, LoadString() will expand
into LoadStringW(), which is just a stub that fails under
Win95.
Submitted by Paula Tomlinson.
------------------------------------------------------------
WDJ SDK Annotation #104
TYPE: Win32
TOPIC: LVN_DELETEITEM
KEYWORD: LVN_DELETEITEM AND QuickInfo
The documentation implies that this notification
arrives after the item is deleted. In fact, it
arrives before the item is deleted from the listview
control.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #105
TYPE: Win32
TOPIC: IsWindow
KEYWORD: IsWindow AND QuickInfo
The documentation claims this function returns TRUE if the
given handle is a valid window handle. That was true under
Windows 3.x and is true under Windows NT, but Windows 95
returns a large non-zero value that is not equal to 1 (nor
is it equal to the window handle). In an un-indexed help
topic in the initial Win95 SDK, Microsoft reveals that
Win95 functions with BOOL return types are only guaranteed
to return non-zero when the documentation claims they
return TRUE. Windows NT appears to behave as documented.
Submitted by: David Lowndes
------------------------------------------------------------
WDJ SDK Annotation #105
TYPE: Win32
TOPIC: GetClientRect
KEYWORD: GetClientRect AND QuickInfo
The documentation claims this function returns TRUE if the
given handle is a valid window handle. That was true under
Windows 3.x and is true under Windows NT, but Windows 95
returns a large non-zero value that is not equal to 1 (nor
is it equal to the window handle). In an un-indexed help
topic in the initial Win95 SDK, Microsoft reveals that
Win95 functions with BOOL return types are only guaranteed
to return non-zero when the documentation claims they
return TRUE. Windows NT appears to behave as documented.
Submitted by: Ron Scott
------------------------------------------------------------
WDJ SDK Annotation #106
TYPE: Win32
TOPIC: WM_GETDLGCODE
KEYWORD: WM_GETDLGCODE AND QuickInfo
The documentation WM_GETDLGCODE states that this message has
no parameters. But the truth is that if the user presses a
key, lParam will contain a pointer to a MSG structure
containing information about the event that made Windows send
the WM_GETDLGCODE message. This is indirectly documented in
windowsx.h, where the HANDLE_WM_GETDLGCODE() macro passes
two arguments to the handler: the window handle and (MSG
FAR*)(lParam).
Submitted by: Patrick Tennberg
Reference: Microsoft Knowledge Base article Q83302
------------------------------------------------------------
WDJ SDK Annotation #107
TYPE: Win32
TOPIC: DBT_DEVICEQUERYREMOVE
KEYWORD: DBT_DEVICEQUERYREMOVE AND QuickInfo
The documentation incorrectly says that you should return
FALSE if you want to veto the device removal. In fact, you
have to return BROADCAST_QUERY_DENY; returning FALSE will
allow the device removal to proceed.
Submitted by Paula Tomlinson.
------------------------------------------------------------
WDJ SDK Annotation #108
TYPE: Win3.1
TOPIC: LZOpenFile
KEYWORD: LZOpenFile AND QuickInfo
However, if lpszFile contains only a filename and extension
(i.e. no path is specified), then LZOpenFile() use the same
searching logic as OpenFile(). If no file with the matching
name (and extension) is found, then it searches for the
compressed filename. The compressed file has a _ as the
last character (e.g., the compressed version of "readme.txt"
is "readme.tx_"). Therefore if you use LZOpenFile() to open
a file called "readme.txt", it searches as follows:
1) it looks for "readme.txt" using the same search
algorithm as OpenFile().
2) if the file was not found, it uses the same
algorithm to search for "readme.tx_".
That means LZOpenFile() might open a "readme.tx_" file from
a directory other than the one you expected. Even if you
specify the complete filename (such as
"c:\demo\readme.txt"), LZOpenFile() first searches for the
specified file, and if the specified filename is not found,
it searches for the compressed file in the same directory
("c:\demo\readme.tx_").
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #109
TYPE: Win32
TOPIC: SetCapture
KEYWORD: SetCapture AND QuickInfo
This help topic does not document the fact that when the
mouse is captured, menu hotkeys (for example, Alt+F for
accessing the File menu) and other keyboard accelerators do
not work (ex: Alt+F4). This is because DefWindowProc()
handles the WM_SYSCHAR and WM_SYSCOMMAND messages
differently if the mouse has been captured (by any window).
DefWindowProc() processes the WM_SYSCHAR message to check if
the pressed key is a menu hotkey (Alt+F for example). If it
is, then it causes the menu to drop down. However, if the
mouse is captured, it does not do the above action.
Whenever DefWindowProc() sees a WM_SYSCOMMAND and finds that
the mouse is captured, then it does nothing.
Submitted by V. Ramachandran.
------------------------------------------------------------
WDJ SDK Annotation #110
TYPE: Win32
TOPIC: RegCreateKey
KEYWORD: RegCreateKey AND QuickInfo
The documentation for RegCreateKey(), RegCreateKeyEx(),
RegOpenKey(), and RegOpenKeyEx() all list several predefined
handles you can use, such as HKEY_CURRENT_USER. However,
they fail to document the predefined key
HKEY_CURRENT_CONFIG, which has a structure similar to the
registry tree under HKEY_LOCAL_MACHINE, but is for storing
information specific to the current hardware profile.
Submitted by Paula Tomlinson.
------------------------------------------------------------
WDJ SDK Annotation #111
TYPE: Win32
TOPIC: CreateFile
KEYWORD: CreateFile AND QuickInfo
The documentation claims CreateFile() returns a handle that
can be used to access the object. However, under both NT
and Win95, CreateFile() will appear to succeed and return a
valid handle if you attempt to open a file with
GENERIC_WRITE permissions on a read-only medium (e.g.,
protected floppy or CD-ROM). If you then try to perform a
write with the returned handle, that will fail.
Submitted by: David Lowndes
------------------------------------------------------------
WDJ SDK Annotation #112
TYPE: Win32
TOPIC: GetWindowText
KEYWORD: GetWindowText AND QuickInfo
The third argument is the "maximum numbers of characters to
copy". It may not be clear that this number must include
the NULL byte so, for example, it never makes sense to set
this argument to 1 since all you could get back is a NULL
byte. If you want to use GetWindowText() to retrieve a
single character (e.g., from an edit control), you would
have to specify a length of 2 -- one for the character and
one for the terminating NULL byte.
Submitted by: Tony Yuricich
------------------------------------------------------------
WDJ SDK Annotation #113
TYPE: Win32
TOPIC: keybd_event
KEYWORD: keybd_event AND QuickInfo
You can use this function to toggle keys such as the Caps
Lock, Scroll Lock, and Num Lock. Unfortunately, though
toggling these three keys works correctly under NT, you
cannot use this function to toggle the Num Lock key under
Win95.
------------------------------------------------------------
WDJ SDK Annotation #114
TYPE: Win3.1
TOPIC: WM_CTLCOLOR (2.x)
KEYWORD: WM_CTLCOLOR AND QuickInfo
The documentation incorrectly states that "the return value
from this message has no effect on a button with the
BS_PUSHBUTTON or BS_DEFPUSHBUTTON style." In fact, returning
a brush handle in response to this message appears to
determine the color of the pushbutton window background,
which is visible as the tiny areas in the corners of the
pushbutton window. Note that under Windows 95, pushbuttons
fill the entire client area of their windows, thus hiding
the window background from view.
Submitted by: Forest Wilkinson
------------------------------------------------------------
WDJ SDK Annotation #115
TYPE: Win32
TOPIC: GlobalDeleteAtom
KEYWORD: GlobalDeleteAtom AND QuickInfo
The documentation for GlobalDeleteAtom states:
"The only way to ensure that an atom has been deleted from the
atom table is to call this function repeatedly until it fails."
Unfortunately, a 32-bit program running under Win NT 3.51 never fails,
making for an infinite loop (Windows 95 functions as documented).
Microsoft says this may be fixed in the next release (NT 4.0).
Submitted by Ken Brown
------------------------------------------------------------
WDJ SDK Annotation #116
TYPE: Win32
TOPIC: LB_ADDSTRING
KEYWORD: LB_ADDSTRING AND QuickInfo
If your listbox has the WS_HSCROLL style, and if you are
adding a string wider than the listbox, you may have to send
a LB_SETHORIZONTALEXTENT message to make the horizontal
scrollbar appear. The listbox does not automatically check
each newly added string and add the horizontal scrollbar
when a too-wide string is added or inserted.
------------------------------------------------------------
WDJ SDK Annotation #117
TYPE: Win32
TOPIC: LB_DIR
KEYWORD: LB_DIR AND QuickInfo
If you pass a long filename to LB_DIR, it works
under NT 3.51, but fails under Win95 because it
relies on the 16-bit listbox which was not changed
to handle long filenames. You can avoid the error
by first translating the filename to a short filename
by calling GetShortPathName(). The LB_DIR will not
fail, but it will still display only the short versions
of any long filenames in the subdirectory.
Reference: Microsoft Knowledge Base article Q131286
------------------------------------------------------------
WDJ SDK Annotation #118
TYPE: Win32
TOPIC: ReadFile
KEYWORD: ReadFile AND QuickInfo
The documentation correctly points out that Win95
does not support OVERLAPPED I/O. However, it incorrectly
states that you must pass a pointer to a structure of
type OVERLAPPED if the file was created (or opened)
with the flag FILE_FLAG_OVERLAPPED. In fact, if you
pass a pointer (rather than NULL) under Windows 95,
ReadFile() returns FALSE, and GetLastError() returns
ERROR_INVALID_PARAMETER, whether or not the file
was created/opened with the FILE_FLAG_OVERLAPPED
flag. That means that if you want to code a call
to ReadFile() that works correctly for both
synchronous and asynchronous I/O, you must detect
at runtime that you're running under Win95 and
treat that case differently.
-----------------------------------------------------------------------
WDJ SDK Annotation #119
TYPE: Win32
TOPIC: WinMain
KEYWORD: WinMain AND QuickInfo
Note that the string passed in lpCmdLine is not the same as
the string returned by GetCommandLine(). The string in
lpCmdLine contains the command line arguments only, but
GetCommandLine() returns the program name followed by the
arguments.
If you specify the following command: 'winword abc.doc', and
winword exists in d:\msoffice\winword.exe, lpCmdLine will
contain 'abc.doc', while GetCommandLine will return
'"d:\msoffice\winword.exe" abc.doc' Note the double quotes
around the exe name.
Submitted by Phil Rodgers.
----------------------------------------------------------------------
WDJ SDK Annotation #119
TYPE: Win32
TOPIC: GetCommandLine
KEYWORD: GetCommandLine AND QuickInfo
Note that the string passed in the lpCmdLine parameter to
WinMain is not the same as the string returned by
GetCommandLine(). GetCommandLine() returns the complete
program name enclosed in double quotes, followed by the
arguments; whereas the lpCmdLine parameter of WinMain
contains the command line arguments only.
If you specify the following command: 'winword abc.doc', and
winword exists in d:\msoffice\winword.exe, lpCmdLine will
contain 'abc.doc', while GetCommandLine will return
'"d:\msoffice\winword.exe" abc.doc' Note the double quotes
around the exe name.
Submitted by Phil Rodgers.
----------------------------------------------------------------------
WDJ SDK Annotation #120
TYPE: Win32
TOPIC: ShellAbout
KEYWORD: ShellAbout AND QuickInfo
The documentation says that in Windows 95 ShellAbout will
prepend "Microsoft Windows" to the title of the application.
This is not true. Actually, this function prepends only
"Microsoft", so if your app is called "MyApp", the title
will read "Microsoft MyApp".
Submitted by Luis A. Ramos.
----------------------------------------------------------------------
WDJ MFC Annotation #121
TYPE: MFC 4
TOPIC: CPropertySheet::SetTitle
KEYWORD: SetTitle AND QuickInfo
The parameters to this function are interchanged: it should
actually read:
void SetTitle (LPCTSTR lpszText, UINT nStyle);
Submitted by Margaret M. O'Connell.
----------------------------------------------------------------------
WDJ MFC Annotation #122
TYPE: MFC 1.5x
TOPIC: CCmdTarget::GetIDispatch
KEYWORD: GetIDispatch AND QuickInfo
The MFC 1.5x documentation incorrectly states that this
function takes no parameters. It should read:
LPDISPATCH GetIDispatch (BOOL bAddRef)
bAddRef - specifies whether to increment
the reference count for the object.
This has been corrected in the MFC 4.0 documentation.
Submitted by V.Ramachandran.
----------------------------------------------------------------------
WDJ SDK Annotation #123
TYPE: Win16
TOPIC: LB_SELECTSTRING
KEYWORD: LB_SELECTSTRING
win31wh.hlp fails to mention that this message works only
with single select listboxes. For multi-select listboxes it
returns LB_ERR.
Submitted by Dino Esposito.
----------------------------------------------------------------------
WDJ SDK Annotation #124
TYPE: Win32
TOPIC: AdjustWindowRect
KEYWORD: AdjustWindowRect AND QuickInfo
The documentation for AdjustWindowRect() and
AdjustWindowRectEx() has a number of problems.
1. Though the documentation says that window titles and
borders are not taken into account, they function does
account for these styles.
2. Add 1 to the rect.bottom returned by this function.
There is a one-off error in the y direction.
3. The meaning of the rect parameter is not well explained.
The input to AdjustWindowRectEx is the window coordinates of
the top-left and bottom-right corners of the desired client
area. AdjustWindowRectEx inflates the specified rectangle
to include the caption, border and other non-client objects
specified by the style parameter.
Reference: MSDN Dr.GUI #10 - Calculated Client Window Size.
Submitted by Etay Szekely.
----------------------------------------------------------------------
WDJ SDK Annotation #124
TYPE: Win32
TOPIC: AdjustWindowRectEx
KEYWORD: AdjustWindowRectEx AND QuickInfo
The documentation for AdjustWindowRect() and
AdjustWindowRectEx() has a number of problems.
1. Though the documentation says that window titles and
borders are not taken into account, they function does
account for these styles.
2. Add 1 to the rect.bottom returned by this function.
There is a one-off error in the y direction.
3. The meaning of the rect parameter is not well explained.
The input to AdjustWindowRectEx is the window coordinates of
the top-left and bottom-right corners of the desired client
area. AdjustWindowRectEx inflates the specified rectangle
to include the caption, border and other non-client objects
specified by the style parameter.
Reference: MSDN Dr.GUI #10 - Calculated Client Window Size.
Submitted by Etay Szekely.
----------------------------------------------------------------------
WDJ MFC Annotation #125
TYPE: MFC 3.1 and 3.2
TOPIC: CImageList::DeleteObject
KEYWORD: DeleteObject AND QuickInfo
VC++ 2.1 and 2.2 help files incorrectly documented this
function to delete image lists, while it actually never
existed. The correct function to delete an image list is
CImageList::DeleteImageList(); it returns non-zero if
successful and zero if it fails.
This error is corrected in the VC++ 4.0 documentation.
Submitted by Barry Tannenbaum.
----------------------------------------------------------------------
WDJ SDK Annotation #126
TYPE: Win32
TOPIC: AVIFileOpen
KEYWORD: AVIFileOpen
The documentation specifies that using the OF_CREATE flag
will cause an existing file to be truncated to zero length.
In reality, it has no effect: the file length remains the
same, and the old data is intact once the file is closed.
Submitted by Tim Lesher.
----------------------------------------------------------------------
WDJ SDK Annotation #127
TYPE: Win16
TOPIC: CBTProc
KEYWORD: CBTProc
The CBTProc documentation fails to mention that you can
return 0 to allow the operation and 1 to prevent it for
HCBT_SETFOCUS notification also. The documentation has been
corrected in the Win32 help file.
Submitted by V.Ramachandran.
----------------------------------------------------------------------
WDJ SDK Annotation #128
TYPE: Win32
TOPIC: GetDialogBaseUnits
KEYWORD: GetDialogBaseUnits AND QuickInfo
GetDialogBaseUnits() does not return correct dialog base
units if the dialog is not using the system font. Use the
following function instead:
DWORD WDJ_GetDialogBaseUnits (HWND Dialog)
{
int BaseX, BaseY;
RECT R;
SetRect (&R, 0, 0, 4, 8);
MapDialogRect (Dialog, &R);
BaseX = R.right;
BaseY = R.bottom;
return (DWORD)MAKELONG (BaseX, BaseY);
}
Reference: p54, January 1996 Windows Developer's Journal.