home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-02 | 70.9 KB | 1,916 lines |
-
-
-
-
-
- WW WW WW PPPPPPPP JJ
- WW WW WW PP PP JJ
- WW WWWW WW PP PP JJ
- WW WW WW WW PPPPPPPP JJ
- WW WW WW WW PP JJ JJ
- WWWW WWWW PP JJ JJ
- WW WW PP JJJJJ
-
- ----------------------------------------------------------------
- The Windows Programmer's Journal Volume 01
- Copyright 1992 by Peter J. Davis Number 01
- and Mike Wallace Jan 93
- ----------------------------------------------------------------
- A monthly forum for novice-advanced programmers to share ideas and concepts
- about programming in the Windows (tm) environment.
-
- You can get in touch with the editor via Internet or Bitnet at:
-
- HJ647C at GWUVM.BITNET or HJ647C at GWUVM.GWU.EDU
-
- CompuServe: 71141,2071
-
- or you can send paper mail to:
-
- Windows Programmer's Journal
- 9436 Mirror Pond Dr.
- Fairfax, Va. 22032
-
- The two GWUVM IDs are Pete's and CompuServe is Mike's.
-
- We can also be reached by phone at: (703) 503-3165.
-
- Microsoft, MS-DOS, Microsoft Windows, Windows NT, Windows for Workgroups,
- Windows for Pen Computing, Win32, and Win32S are registered trademarks of
- Microsoft Corporation.
-
- Turbo Pascal for Windows, Turbo C++ for Windows, and Borland C++ for
- Windows are registered trademarks of Borland International.
-
- WordPerfect is a registered trademark of WordPerfect Corporation.
-
- The Windows Programmer's Journal takes no responsibility for the content of
- the text within this document. All text is the property and responsibility
- of the individual authors. The Windows Programmer's Journal is solely a
- vehicle for allowing articles to be collected and distributed in a common
- and easy to share form. No part of the Windows Programmer's Journal may be
- re-published or duplicated in part or whole, except in the complete and
- unmodified form of the Windows Programmer's Journal, without the express
- written permission of each individual author. The Windows Programmer's
- Journal may not be sold for profit without the express written permission
- of the Editor, Peter J. Davis, and only then after he has obtained
- permission from the individual authors.
-
-
-
-
-
-
-
-
-
-
-
-
- Table of Contents
-
- Subject Page Author(s)
- -----------------------------------------------------------------
- WPJ.INI ...................................... 3 Pete Davis
-
- Off Topic .................................... 6 Pete & Mike
-
- Beginner's Corner (C) ........................ 8 Pete Davis
- & Mike Wallace
-
- A Drag and Drop Trashcan (TPW) ............... 16 Andreas Furrer
-
- Using DDE to Communicate With Program Manager. 18 Pete Davis
-
- Implementing a Linked List in the Global Heap. 22 Mike Wallace
-
- Book Review .................................. 26 Pete Davis
-
- Last Page .................................... 28 Mike Wallace
-
- Getting in Touch with Us ..................... 29 Pete & Mike
-
-
-
-
- Windows Programmer's Journal Staff:
-
- Publishers ......................... Pete Davis and Mike Wallace
- Editor-in-Chief .................... Pete Davis
- Managing Editor .................... Mike Wallace
- Contributing Writer ................ Andreas Furrer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- WPJ.INI
-
-
- First of all, I'd like to introduce myself. My name is Pete Davis and
- I was the editor of the Pascal NewsLetter, a journal similar to this one
- which lasted 1 year for 6 issues. I unfortunately had an accident which
- left me unable to continue the newsletter for some time. By the time I was
- back in shape and ready to go, someone had picked up the newsletter and
- re-started it. It was nice to see that there was enough interest that it
- could continue without me. In the past year I have developed an interest in
- Windows programming using C, so I guess at this point, I'm more suited to
- Windows programming anyway.
-
- Well, it sure is nice to have a "magazine" again. I guess I have the
- same problem now that I had with the Pascal NewsLetter: What is it? A
- magazine? A Journal? A NewsLetter? Well, I never quite got it figured out.
- The Pascal NewsLetter was originally intended to be just that, a
- newsletter, but in its prime it was over 30 pages single-spaced, so it
- wasn't exactly a newsletter.
-
- What, you may ask, is the purpose of this thing anyway? Well, I love
- to program. I know a lot of other people out there, techno-geeks like
- myself, love it also. As with Pascal, I'm finding there aren't a whole lot
- of magazines which cover Windows programming. That's fine, it just leaves
- more readers for us, I suppose. Not to mention, this is free. There aren't
- any free ones for Windows programming (or if there are, I haven't heard of
- them). I like to teach people how to program and I can't think of an easier
- way to get such a large audience and have it all be free.
-
- In this magazine, you won't just be hearing Mike and I ramble on, but
- you'll be hearing from a lot of people. Not professors, not industry
- experts, but people like you and me, regular programmers who like what they
- do and want to share their ideas and experiences with us. No one gets paid
- and no one has to pay. That's the idea.
-
- If the initial response we got, when we first started asking people
- about doing this, is any indication, there are going to be a LOT of
- readers. That means we should also have a lot of writers. You'll find a
- file in this .ZIP file with the name SUBMIT.TXT. It is simple instructions
- on how to submit an article. There aren't any solid rules and it's easier
- than you'd probably expect, so please consider sending in an article.
-
- Right now, things are real open to regular columnists. I had several
- with the Pascal NewsLetter and their columns were very well received.
- Since we don't have a regular columnist for a beginners column yet, Mike
- and I are going to start it up ourselves, but I hope someone will try to
- pitch in and give us a hand with it. When I did the Pascal NewsLetter, I
- had a regular writer for a beginners column and it was the most popular
- column in the magazine. There's a reason for that. There are a lot of
- people trying to get started and just can't seem to get the hang of the
- basics. Programming Windows is a lot different than programming in DOS and
- it's not as easy to pick up, but with a little persistence, anyone can do
- it.
-
- Other columns that we'd like to see are ones that address things like
- C++ for Windows and Turbo Pascal for Windows. We'd like to hear from you if
- you want to tackle any of these. It's not a lot of work and only requires a
- few hours each month. Most of us can make at least that much time.
-
- The Pascal NewsLetter came out irregularly, but we'd really like to do
-
-
-
-
-
-
- this on a monthly basis if possible. If we don't get enough submissions, we
- might have to make it every two months. We should be able to let you know
- by the second or third issue.
-
- As far as things we'd like to see in the newsletter:
-
- * Software and book reviews, maybe even reviews of Windows related
- hardware. I'd like to see reviews every month.
-
- * As I mentioned before, I want a beginners column for plain C for
- Windows as well as one for Turbo Pascal for Windows and C++ for
- Windows.
-
- * As far as one-time articles, perhaps one on programming DLLs and
- special considerations that need to be made for writing them.
-
- * Articles on DDE and OLE programming.
-
- * Articles on network programming in Windows for Workgroups and
- Windows NT.
-
- * Printing text and graphics in Windows
-
- * Memory management
-
- * Using different memory models and how to handle multiple code or
- data segments.
-
- * Programming TCP/IP and Sockets under Windows NT
-
- * Maybe reviews of Windows NT while it's still in the pre-release
- stage to let people who don't have it know what it's like and how
- Microsoft is progressing with it.
-
-
- That should be enough to start with. Please take the time and try to
- contribute. You don't have to be an expert. In the Pascal NewsLetter, the
- beginner's column was written by a guy who was just learning Pascal. He did
- a fantastic job, and as I said earlier, it was the most popular column. I
- had an article submitted to me by someone who didn't speak English very
- well, so he wrote it in his native tongue, German, and I had it translated.
- I had a 16 year-old high school student who submitted a terrific article,
- so anyone can do it. You just need to take the time. The writing in this
- magazine is pretty informal. People seemed to like that about the Pascal
- NewsLetter. They said it was easier to relate to than regular magazines,
- so I'm going to stick with that format.
-
- As for the format, I'm going to try to keep it like I did with the
- Pascal NewsLetter, in that it's just a plain text file with Form Feed
- characters at page breaks. If there's a big push to go with something like
- the Windows Write format, that can be done too. Personally, I prefer using
- WordPerfect (just what I'm used to) and it makes it pretty easy for
- handling formatting and getting articles from different people in different
- formats.
-
- In fact, as far as anything about the magazine, if you have
- suggestions, we'd love to hear them. If you think we should change the way
- we're doing something, then you might not be the only one. If we get enough
- suggestions for things, or if it's just something we should obviously be
- doing then we'll make the change.
-
-
-
-
-
-
- Well, that's enough of my rambling on for now. Hope you guys (and
- gals) like the magazine. I'm open to suggestions and I love to get
- feedback, good and bad, about the magazine, so feel free to get in touch
- with me or Mike at the address on the cover page.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Off Topic
- By Pete and Mike
-
- This is exactly what the title says, off topic. Mike and I have two
- computers that we want to sell, so we figured we may as well throw those in
- here. Both machines are identical. They are:
-
- IBM PS/2 Model 70-486 (8570-B61)
-
- Both machines have 2MB RAM and 60 MB hard drives. They come with 8512
- Color VGA monitors and the IBM Enhanced Keyboards. The machines are less
- than 4 months old and barely used.
-
- The cost is $1,500.00 and includes shipping anywhere in the
- continental United States. Shipping outside of the United States is covered
- by the buyer.
-
- These machines are really in excellent condition. We've checked them
- out thoroughly and there aren't any problems with them. We'll throw in a
- guarantee that if there are problems with them sometime within the first
- month, you can return the computer for a full refund. Of course this
- doesn't include any damage applied after the purchase.
-
- Well, that's our little pitch for our computers. We don't normally
- sell computers, so hopefully this will be the only ad we throw in here for
- computers.
-
- Our next off-topic thing is something Mike and I discussed and both of
- us agreed that it wasn't something we wanted to do but felt that for the
- magazine's best interest, we would. We are asking for donations. Neither of
- us is looking to make a fortune in contributions (And I'd be willing to put
- money down that we don't). The idea behind it is this. We want to be able
- to support Windows programming with different compilers, Windows NT,
- Windows for Workgroups, etc. The donations would be used specifically to
- get the software so we could either work with these environments for our
- own articles or use them to test programs and articles sent in by others.
- Our address is at the end of the article. Send in what you believe this
- magazine is worth. We want to put together the best Windows magazine out
- there, but we're not rich, so we'll do what we can with what we have. If
- you do want to send a donation, see the last page for our address. Make the
- check payable to Pete Davis.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Beginner's Corner
- By Pete Davis and
- Mike Wallace
-
-
- Well, since this is the first issue and we don't have a writer for the
- beginner's column yet, Mike and I are going to split it between the two of
- us. I'm a strong believer in the beginner's column because once you make
- the first few steps, you get hooked. Unfortunately, few books really
- address the beginner so someone has to help them get started. We must
- assume that the reader is familiar with the C language. Covering both a
- beginners column for C and for Windows would be far too great a task. There
- are several good books out for C programming and there's also the C News,
- which, like this magazine is a file which is available on many BBSes and
- the Internet. It's a great place to start learning C and I highly recommend
- it. Also, although formally, all C routines are called functions, we use
- the words procedure, function, and routine fairly interchangeably. A
- function tends to imply that some result is returned to the calling routine
- so I tend to use it in that manner.
-
- In almost every beginners book on programming, the first program
- written is the infamous "HELLO WORLD" program. We're going to do that here,
- but in a sort of round-about way. We're not just going to show you the one
- simple program, but we're going to go to great lengths in explaining the
- different parts of a Windows program first. For example, I'm going to
- specifically cover how Windows works and then the .DEF file which is used
- to tell the compiler how your code and data is supposed to be configured
- when it's linked. Then Mike and I are going to go in-depth into the .RC or
- Resource source file. The .RC file has the definitions of all the resources
- of your program. It has your dialog boxes, menus, icons, bitmaps, etc. We
- won't actually get to the "HELLO WORLD" program itself until the second
- issue.
-
- To a beginner, it may seem a bit overwhelming that we're going to have
- to cover so much just to do a "HELLO WORLD" program, but the truth is, we
- don't HAVE to cover all of it. When you actually see the program, you'll
- see how simple it really is. We'd just like to give you an overview of the
- parts of a Windows program first and then show you a specific example. We'd
- also like this article to be a sort of reference on how to create more than
- just the simple resources and definitions (.RC and .DEF files) for a "HELLO
- WORLD" program.
-
- How Windows Works
-
- Too some of you who are beyond the very basics, some of this you may
- already know, but it may be a good idea to read anyway. Some of this is a
- simplified explanation, but the point is to get the concept easy to
- understand. Later we can be a little more specific.
-
- Windows is what is called a non-preemptive multi-tasking environment.
- A preemptive multi-tasking environment is one where the operating system
- allocates a certain amount of time to each task. It then runs one task
- until it has used its share of time and then runs another task until its
- time has run out and so on until it gets back to the first task. Windows,
- on the other hand, will run a procedure from your program until the
- procedure is completed and then it will run a procedure from another
- program until it is completed. What this means is that a Windows program
- can take over the CPU entirely, if it wants, but that defeats the purpose
- of programming for a multi-tasking environment. (There is one exception,
- and that is DOS sessions running under Windows, which are handled in a
-
-
-
-
-
-
- preemptive manner, but this is not our topic and won't be discussed in this
- column.)
-
- In a Windows program, the initialization of the program first
- 'registers' itself with Windows. It does this by telling Windows a few
- parameters that it needs to know about the program and to set-up the main
- message-loop, then telling Windows where the main window procedure is. A
- message-loop procedure is one that accepts messages from Windows that are
- sent to your program.
-
- Messages in Windows are a way of telling your program what the user
- is doing, or a way for your program to tell Windows or some other program
- what to do. Windows messages usually come in the form of WM_something,
- where the WM_ stands for Windows Message. For example, when you first
- create your Main Window, one of the first messages passed to your procedure
- is WM_CREATE. When you receive the WM_CREATE message, you know Windows is
- about to create your window and if you want to initialize certain variables
- to be handled by that procedure, you want to do it now. Or, if you receive
- the WM_CLOSE message, you know that Windows is about to close your window
- and end your program. You may want to, at this point, ask the user if he
- wants to save his files or ask if he really wants to quit.
-
- Messages are the heart of the Windows multi-tasking environment and
- when we create our "HELLO WORLD" program, you'll see a little more clearly
- how this works.
-
- In your programs, you will create windows and dialog boxes. When you
- do that, you need to tell Windows the name and location of a procedure
- which is going to handle the messages used by the window or dialog box. The
- procedure then gets all messages pertaining to that specific window or
- dialog box. Each of these procedures is a lot like the main window
- procedure to Windows. This is unlike a regular DOS C program in which the
- program always controls which procedure is called next and is responsible
- for making its own calls. In a Windows program, you tell Windows where your
- procedures are and it will run them in response to certain commands and
- user actions.
-
- This may seem a little unclear, but all I can say is stick around
- until the end of the second part of the article and it may make more sense
- in terms of a real program. This is, essentially, how Windows works. If you
- have questions, please feel free to contact us in one of the ways mentioned
- on the first page and we will try to be more clear in the areas readers
- seem confused about in the second part of this article.
-
- The .DEF File
- (Also known as the Module Definition File)
-
- The .DEF file is what the compiler uses to find out how to handle your
- program as a whole and how to handle individual routines in your program.
- We're going to go fairly in-depth into the different things you can do in a
- .DEF file, but in the second part of the article, you'll see a very simple
- application .DEF file and see exactly what parts are basic. I will try to
- distinguish between the things that you always must have and then parts
- that are optional or rarely used.
-
- I will show each parameter, a summary of its purpose and options,
- followed by how it would appear in the .DEF file. The .DEF file is simply
- an ASCII text file that you type in with your program editor.
-
- The first parameter is the NAME. In general, this should be the same
-
-
-
-
-
-
- as the name of the executable. Also, in the cases of Dynamic Link Libraries
- (DLLs), this is replaced by the LIBRARY parameter.
-
- NAME myprog (for a regular Windows program)
- or
- LIBRARY mydll (for a DLL)
-
- The next parameter is the DESCRIPTION. This is inserted into the
- header of your executable, but serves no real purpose other than perhaps
- allowing you to keep track of version and/or copyright information.
-
- DESCRIPTION 'My first Windows Program'
-
- The EXETYPE parameter tells the compiler which environment the program
- will be run under. For Windows, it is simply:
-
- EXETYPE WINDOWS
-
- The next parameter is the WINSTUB program. The WINSTUB is simply the
- name of a program that is run in the event that someone tried to execute a
- Windows program under DOS. This may be familiar to you. The most common
- WINSTUB is the one that says, 'This program requires Microsoft Windows.' In
- theory this program can be almost anything you want. A programmer could,
- for example, have both a DOS and Windows version of his/her program with
- the DOS version simply being a WINSTUB in the Windows version. In a later
- article, I'll provide source code for a WINSTUB that will allow a user to
- run your Window program from DOS. This is done by running Windows with the
- name of the program as the parameter (i.e., the user types 'TESTPROG' and
- the stub from TESTPROG executes the command:
- 'WIN TESTPROG'). The possibilities are enormous and it would be nice at
- some point to see some more creative uses of the WINSTUB besides 'This
- program requires Microsoft Windows.' Anyway, the standard WINSTUB is a
- program called WINSTUB.EXE which comes with most Windows compilers. The
- syntax is as follows:
-
- WINSTUB 'WINSTUB.EXE'
-
- The next section covers the code and data segments. Windows has the
- Small, Medium, Compact and Large memory models. The memory model determines
- whether or not there are multiple code and/or data segments. See the
- following table:
-
- Model # Data Segments # Code Segments
- ----------------------------------------------------------
- Small Single Single
- Compact Multiple Single
- Medium Single Multiple
- Large Multiple Multiple
-
- For now, we'll stick mostly with Small or Medium models, as they're
- the easiest to use. We will go into the different models in later articles
- to discuss the advantages and disadvantages of each and how to program for
- them.
-
- Each code and data segment can have different options telling Windows
- how to handle them. Most segments, you want to give the option MOVEABLE
- which means that the Windows memory manager can move the segment around in
- memory to make room for other things if needed. There may be occasions when
- you would want a segment set to FIXED. For example, if you were writing a
- program that was working with DOS on a fairly low level, it is useful to
-
-
-
-
-
-
- have things set for FIXED so DOS will always know where they are. This is,
- however, in the advanced arena, so we'll be avoiding it.
-
- The PRELOAD option tells Windows to automatically load the segment
- into memory before the program is actually executed. The LOADONCALL option
- tells Windows only to load the segment when it is needed. This helps keep
- memory available for other processes. In general, you want your main CODE
- and DATA segments set for PRELOAD.
-
- The DISCARDABLE option tells the Windows memory manager that it can
- remove that segment from memory all together when it needs more memory. The
- memory manager will then re-load the segment the next time it is needed.
- This is fine for most CODE segments where the contents of the code does not
- change. In DATA segments, the contents of the data will change as the
- program is run and because of this, you do not want it to be discardable.
- The discardable segments are not saved before they are discarded, so any
- changes made to them are lost. Making a DATA segment discardable would give
- unknown results.
-
- The SINGLE option tells windows tells Windows that although there may
- be multiple copies of the program running at once, that this segment may be
- shared. This is useful for a CODE segment where several copies of the same
- program can use the same copy of the code, thus saving memory. The DATA
- segment, however, would be different from one running program to the next,
- so the SINGLE option wouldn't really be appropriate. (Because of the way
- Windows handles DLLs, they data segments MUST be SINGLE. This requires
- special handling on the part of the programmer to handle multiple programs
- using the same DLL. We'll discuss this another day.)
-
- The MULTIPLE option tells Windows to create a separate copy of the
- segment for each copy (instance) of the program that is being executed.
- This is useful for DATA segments. If your CODE segment is single and your
- DATA segment is multiple, you can share the CODE segment and save memory,
- but each copy (instance) of the program will have its own data.
-
- The following is an example for a Small model program. It has one code
- segment and one data segment.
- CODE PRELOAD MOVEABLE
- DATA PRELOAD MOVEABLE MULTIPLE
-
- The next parameters are Heapsize and Stacksize. Heapsize refers to how
- much space is available for local dynamic memory allocation. If you are
- familiar with dynamic memory allocation in regular C programming, then this
- is nothing really new to you. The only real difference is in Windows you
- have Global and Local heaps. For now, let's just keep the Heapsize at about
- 4096. This is a nice safe size for the types of programs we're going to be
- doing for a while.
-
- The stacksize tells Windows how much space to make available for the
- stack. The stack is where Windows keeps a lot of it's variable
- declarations. It also keeps information when you call procedures and
- functions here. As with Heapsize, 4096 should do fine for the time being.
- The syntax is as follows:
-
- HEAPSIZE 4096
- STACKSIZE 4096
-
- The next section is the EXPORTS and IMPORTS sections. The exports are
- procedures that will be called by something other than your own program.
- For example, your main window procedure that receives all the messages
-
-
-
-
-
-
- regarding your main window is an exported procedure. Any procedure that
- accepts messages, for that matter, are Exported. These procedures receive
- their messages from Windows and are called by Windows. Each procedure
- exported should be followed by an @n where n is an integer number. The
- number is an unique index number that Windows uses to help it keep your
- program organized. It's not required, but it does help speed things up for
- Windows and I suggest you use it all the time.
-
- Imports are functions that you want to use from external sources, like
- a DLL, or some other source. To use those, you simply need to list them. If
- they come from a DLL, you need to do the name in the form of:
- DLLNAME.FUNCTIONNAME.
-
- EXPORTS MainWndProc @1
- ADlgProc @2
-
- IMPORTS SHELL.DRAGQUERYFILE
-
-
- Well, that about covers the .DEF file. As we start to use it more
- regularly, you'll see how the different sections affect the program. So,
- we'll end this section with a sample .DEF file.
-
-
- NAME MYPROG
- DESCRIPTION "My first Windows program"
- EXETYPE WINDOWS
- STUB 'WINSTUB.EXE'
- CODE PRELOAD MOVEABLE
- DATA PRELOAD MOVEABLE MULTIPLE
- HEAPSIZE 4096
- STACKSIZE 4096
- EXPORTS MainWndProc @1
-
-
-
-
- The .RC File
-
- The .RC file is used to define the resources for a Windows
- application. Resources include icons, cursors, menus, dialog boxes,
- bitmaps, fonts, string tables, accelerators, custom resources and version
- information; in other words, the gist of a Windows program. The .RC file
- can contain either definitions for one or more of each of these resource
- types or tell Windows where to find the definition(s). I'll start with the
- dialog box format this issue.
-
- A dialog box is a type of window allowing the user to, for example,
- select an item from a list box, pick a printer, select a drive for a file
- directory, etc. In other words, whenever you want to display information
- to the user or get input, use a dialog box. The "About" box is a dialog
- box. The difference between a dialog box and a window is that a window is
- normally used for drawing graphics and a dialog box displays text
- ("dialog"). You define a dialog box with the DIALOG statement, which has
- the following format:
-
- name DIALOG [load option] [memory option] col, row, width, height
- [option statements]
- BEGIN
- [dialog box items]
-
-
-
-
-
-
- END
-
- Description of parameters:
-
- name - unique (to your program) name for the dialog box
-
- load option - determines when the dialog box is loaded into memory;
- if specified, must be either PRELOAD or LOADONCALL. PRELOAD tells Windows
- to load the dialog box when the application starts. This makes the box
- appear quicker, but takes up memory since it must stay in memory throughout
- execution of your program, even if your program never loads it (based on
- user input, for example). The default, LOADONCALL, tells Windows to load
- it when necessary.
-
- memory option - combination of FIXED, MOVEABLE and DISCARDABLE. This
- should normally be "MOVEABLE DISCARDABLE" (notice there's no comma). See
- the article "Implementing a Linked List in the Global Heap" elsewhere in
- this issue for a discussion of these attributes.
-
- row,col,width,height - position and size of the dialog box; col
- (column) and row specify the location of the upper left corner of the
- dialog box relative to the upper left corner of the window which called it.
- All dimensions are in dialog base units.
-
- option stmts - describe the dialog box; can include the STYLE,
- CAPTION, MENU, CLASS and FONT. These are described below.
-
- STYLE - Format "STYLE style". Valid values for style are a
- subset of the styles for windows. Any window style starting with WS_
- or DS_ can be used (except for WS_MINIMIZEBOX and WS_MAXIMIZEBOX), and
- combined with "|". These are listed below:
-
- DS_LOCALEDIT - Forces memory used by dialog boxes into the application's
- data segment.
-
- DS_MODALFRAME - Creates a dialog box with a modal frame.
-
- DS_NOIDLEMSG - No WM_ENTERIDLE messages are sent from the dialog box if
- created with this style. WM_ENTERIDLE messages are normally used to alert
- the application that the dialog box is displayed but no user activity has
- happened yet.
-
- DS_SYSMODAL - System modal dialog box. This means no other window can gain
- the input focus until this dialog box is closed.
-
- WS_BORDER - Border on the dialog box.
-
- WS_CAPTION - Caption on the dialog box; can't be used with WS_DLGFRAME
-
- WS_CHILD - Create a child dialog box; can't be used with WS_POPUP.
-
- WS_CHILDWINDOW - Same as WS_CHILD.
-
- WS_CLIPCHILDREN - When creating a parent dialog box, specifies that child
- dialog boxes will be clipped at the boundary of the parent.
-
- WS_CLIPSIBLINGS - Used with WS_CHILD; keeps "sibling" dialog boxes from
- overlapping.
-
- WS_DISABLED - the dialog box is initially disabled (cannot receive the
-
-
-
-
-
-
- input focus).
-
- WS_DLGFRAME - Double border.
-
- WS_GROUP - The control can be reached via the direction keys (arrows).
-
- WS_HSCROLL - Horizontal scroll bar.
-
- WS_ICONIC - Initially iconic; used with WS_OVERLAPPED.
-
- WS_MAXIMIZE - Initially maximized.
-
- WS_MAXIMIZEBOX - Maximize box in the upper right corner.
-
- WS_MINIMIZE - same as WS_ICONIC.
-
- WS_MINIMIZEBOX - Minimize box in the upper right corner.
-
- WS_OVERLAPPED - Caption and border.
-
- WS_OVERLAPPEDWINDOW - Combination of WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU
- and WS_THICKFRAME (standard parent window style).
-
- WS_POPUP - Popup dialog box (can't be used with WS_CHILD).
-
- WS_POPUPWINDOW - Combination of WS_POPUP, WS_BORDER and WS_SYSMENU
- (standard popup window style)
-
- WS_SYSMENU - System menu.
-
- WS_TABSTOP - Specifies at which control the tab key stops.
-
- WS_THICKFRAME - Thick frame (used to size the dialog box).
-
- WS_VISIBLE - Initially visible.
-
- WS_VSCROLL - Vertical scroll bar.
-
- Example : STYLE DLGFRAME | WS_VISIBLE
-
-
- CAPTION - Format "CAPTION text". Gives a caption of "text" to
- dialog boxes defined with the WS_CAPTION style.
-
- MENU - Format "MENU menuname". Assigns menu "menuname" to the
- dialog box. The menu is normally defined in the .RC file.
-
- CLASS - Format "CLASS classname". Causes a class other than the
- class of the parent window to be used for the dialog box.
-
- FONT - Format "FONT pointsize, typeface". Determines the font
- size used for the dialog box, which in turn determines the sizing of
- every control and the dialog box itself. Example : FONT 10, "Helv"
-
-
-
- Defining Dialog Box Items:
-
- Defining the objects in a dialog box (e.g., a check box) occurs
- between the "BEGIN" and "END" statements. A lot of these control
-
-
-
-
-
-
- statements have as part of their parameter list "col, row, width, height".
- These give the size and location of the object, and must be integers. Some
- objects have a "text" field, which can be any string enclosed in quotes
- (e.g., "Cancel"). Most of the time, the optional "style" parameter can be
- either WS_TABSTOP or WS_GROUP or the two combined using "|". The "id"
- parameter is a unique identifier assigned by the programmer, with the
- exception of static text controls, which are usually given an ID value of -
- 1 since they are never selected. The control statements are described
- below:
-
- CHECKBOX - Format "CHECKBOX text, id, col, row, width, height [, style]".
- Defines a check box control.
-
- COMBOBOX - Format "COMBOBOX id, col, row, width, height [,style]". Defines
- a combo box control. This is a combination of an edit control and a drop-
- down list box. The optional style parameter can include any combination of
- WS_TABSTOP, WS_GROUP, WS_DISABLED and WS_VSCROLL.
-
- CONTROL - Format "CONTROL text, id, class, style, col, row, width, height".
- Specifies all forms of child window controls within a dialog box. The
- "class" parameter can be either "button", "combobox", "edit", "listbox",
- "scrollbar" or "static". The "style" parameter can be any of the allowed
- values for CreateWindow().
-
- CTEXT - Format "CTEXT text, id, col, row, width, height [, style]".
- Defines a centered static text control.
-
- DEFPUSHBUTTON - Format "DEFPUSHBUTTON text, id, col, row, width, height [,
- style]". Defines the default pushbutton for a dialog box.
-
- EDITTEXT - Format "EDITTEXT id, col, row, width, height [, style]".
- Defines an editable text control in a dialog box. The style parameter can
- be any combination of WS_TABSTOP, WS_GROUP, WS_VSCROLL, WS_HSCROLL,
- WS_BORDER and WS_DISABLED. Text is aligned based on ES_LEFT, ES_CENTER or
- ES_RIGHT.
-
- GROUPBOX - Format "GROUPBOX text, id, col, row, width, height [, style]".
- Draws a rectangle with a title at the top left around a group of other
- controls.
-
- ICON - Format "ICON text, id, col, row [, style]". Places an icon in the
- dialog box. The "text" parameter is the name of the icon as defined
- elsewhere in the .RC file with an ICON statement. The only allowed style
- is SS_ICON.
-
- LISTBOX - Format "LISTBOX id, col, row, width, height [, style]". Places a
- list box in the dialog box. An example of a list box is, if you run a
- Windows application and select "File Open..." from the menu bar, the box
- that appears with a list of the filenames available for opening. Possible
- values for "style" are any styles allowed in CreateWindow().
-
- LTEXT - Format "LTEXT text, id, col, row, width, height [,style]". Defines
- a left-justified static text control.
-
- PUSHBUTTON - Format "PUSHBUTTON text, id, col, row, width, height [,
- style]". Defines a pushbutton for a dialog box. The allowed styles are
- WS_TABSTOP, WS_DISABLED and WS_GROUP.
-
- RADIOBUTTON - Format "RADIOBUTTON text, id, col, row, width, height [,
- style]". Defines a radio button in a dialog box.
-
-
-
-
-
-
- RTEXT - Format "RTEXT text, id, col, row, width, height [,style]". Defines
- a right-justified static text control.
-
- SCROLLBAR - Format "SCROLLBAR id, col, row, width, height [, style]".
- Defines a scroll bar within a dialog box.
-
-
- Here is an example of the DIALOG statement that could be used for
- showing a list of printers and letting the user select one. It includes a
- list box to hold the printer names and three buttons: OK, RESET and CANCEL.
-
-
- IDL_PRINT DIALOG LOADONCALL MOVEABLE DISCARDABLE 78, 40, 124, 58
- CAPTION "Select a Printer"
- STYLE WS_OVERLAPPED | WS_DLGFRAME | WS_CAPTION | WS_POPUP
- BEGIN
- LISTBOX IDL_LIST, 32, 6, 60, 27, LBS_STANDARD |WS_HSCROLL |WS_BORDER
- DEFPUSHBUTTON "OK", IDL_OK, 4, 40, 37, 14, WS_GROUP
- PUSHBUTTON "Reset", IDL_RESET, 44, 40, 37, 14, WS_GROUP
- PUSHBUTTON "Cancel", IDL_CANCEL, 84, 40, 37, 14, WS_GROUP
- END
-
-
- That's all for now about dialog boxes. We'll continue next month with
- more resource types. If you don't like the format and have an idea for a
- better one, drop us a note.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programming Drag&Drop with Windows 3.1
- by Andreas Furrer
-
-
- This article describes writing applications that uses Drag&Drop. At
- the end of this article is an example of an application that makes the use
- of Drag&Drop. The program is written in Turbo Pascal for Windows (1.0), but
- many of the things you'll learn in this article will port to other
- languages.
-
- A nice new feature of Windows 3.1 is Drag&Drop (D&D). With D&D you can
- use the File Manager to select files and drop them onto an application to
- perform some action on the files (e.g., print them).
-
- In Windows 3.1 there are a lot of applications that make use of D&D.
- For example, if you want to read a text file you can simply pick it up in
- File Manager and drop it onto the window or the icon for Notepad or you can
- print files by dropping them onto your Print Manager.
-
- You can also use D&D for your own applications.
-
- D&D is supported by the new SHELL.DLL. There are four procedures and
- one new message. The declarations in Pascal are:
-
-
- const wm_DropFiles = $0233;
-
- procedure DragAcceptFiles(Wnd: HWnd; Accept: Bool);
- external 'SHELL' index 9;
-
- function DragQueryFile(Drop: THandle; FileIndex: Word;
- FileName: PChar;MaxChars: Word): Word;
- external 'SHELL' index 11;
-
- function DragQueryPoint(Drop: THandle; var Pt: TPoint): Bool;
- external 'SHELL' index 13;
-
- procedure DragFinish(Drop: THandle);
- external 'SHELL' index 12;
-
- To use D&D with your application, you first have to register at least
- one Window of your application to accept dropped files.
- This will be done by:
-
- DragAcceptFiles(HWindow,true);
-
- Now this HWindow will receive wm_DropFiles message if some files are
- dropped onto it. If you want to undo the registration just pass false as
- the second parameter to the function above. This should always be done when
- your window is destroyed.
-
- If someone drags some files onto your window you will receive a
- wm_DropFiles message. The word parameter (wparam) of this message is a
- handle to a global data structure. This structure contains information
- about the dropped files and you have to use this handle for all Drag&Drop
- procedures. LParam is not used with this message.
-
- Now you can get information about the dragged files. You have to use
- the following two functions:
-
-
-
-
-
-
-
- DragQueryFile:
-
- function DragQueryFile(Drop: THandle; FileIndex: Word;
- FileName: PChar;MaxChars: Word): Word;
- external 'SHELL' index 11;
-
- With this function you will get the filename of one of the dragged
- files. You have to pass the handle of the D&D structure (received by
- wm_DropFiles), the index of the file (0 is the first), a buffer for the
- filename and the size of the buffer to this function. The function will
- copy the filename into the buffer and return the number of copied chars. To
- get the number of dropped files you can use $ffff as index.
-
- DragQueryPoint:
-
- function DragQueryPoint(Drop: THandle; var Pt: TPoint): Bool;
- external 'SHELL' index 13;
-
- With this function you can get the position of the cursor at the
- moment when the files were dropped. You have to pass the handle for the D&D
- structure (received by wm_DropFiles), and a variable of type TPoint to this
- function. The return value is true, if the files were dropped in the client
- area of the window, otherwise (for the non-client area) it is false.
-
- At the end of your D&D procedure you have to tell Windows to release
- the memory of the D&D data structure. This will be done with the DragFinish
- function. Again you have to pass the handle of the D&D structure to this
- function.
-
- A simple application for demonstrating D&D is a Trashcan. The
- accompanying code will implement a Trashcan which will delete all files and
- directories you dropped into its icon. See the TRASH.PAS file.
-
- After starting Trashcan, you can easily delete files and directories.
- Just select the files or directories in File Manager and drag them onto the
- icon of trashcan. If you have selected a hidden, read-only or a system
- file, you will be asked if you really want to delete it.
-
- To build Trashcan, you first have to open TRASH.RC with the resource
- workshop and save it as TRASH.RES in the .RES format. Now you can compile
- TRASH.PAS and you will get TRASH.EXE.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A Custom Install Program: Part I
- Using DDE to Communicate with Program Manager
- By Pete Davis
-
- This is going to be a four part article on writing an Install program
- for Windows applications. I haven't completed the program yet so I don't
- even know exactly how it's going to turn out. My main problem at this point
- is that I really want to have a file compression algorithm for the files to
- be installed. The main problem is my laziness. I'm not really in the mood
- to write a unzip program, but since I'm having trouble coming up with
- alternatives, that may be my only possibility.
-
- This program is going to be loosely based on one I wrote in the past.
- I can't use any of that code because it is now the property of someone
- else, so I have to start from scratch. There are essentially three main
- sections which I will discuss separately. There's the part that runs last
- (which I'll be discussing first) which involves telling Program Manager to
- create our program group(s) and application icon(s). The second part reads
- and interprets a SETUP.INF file to get parameters of the installation, such
- as what files are to be installed, what disk they're on, whether or not
- they're executables, what is the default directory, etc. The third part is
- the previously mentioned decompression routines. (If anyone has a
- decompression algorithm they'd like to donate, that would be terrific.) The
- last article will tie all these parts together and make them all work
- together.
-
- One thing of extra interest will be that the decompression routines
- will be in a DLL. When I originally wrote my first install program, the
- UNZIP algorithm I used required a lot of memory and it was either make it a
- DLL or give it it's own data segment. I still haven't spent enough time
- with multiple data segment programs, so I stuck with the easy (or so I
- thought) method, the DLL.
-
- The first part I want to discuss is using DDE to communicate with
- Program Manager. This was the most challenging part for me the last time I
- wrote an Install program, so it seems to me that it would be the part that
- would be most interesting for a lot of people.
-
- My first few attempt at creating program groups were pathetic cludges.
- My main aim at the time was just to create the program group files myself
- and make the appropriate modifications to the PROGMAN.INI file. This turned
- out to be a little more difficult than I expected and I soon abandoned it.
- The next thought was to just create my own program group files and install
- them as part of the installation process. This was a workable solution but
- would not allow for installing the code in anything but the default
- directory.
-
- About the time I was mulling over the good and bad points of the last
- option, I came across a little snippet about using DDE to communicate with
- Program Manager. After a lot of reading and looking at source code from
- different sources I finally got a handle one it. This, incidentally, was my
- first attempt with DDE so it was doubly challenging.
-
- My first attempt at the DDE was itself a bit of a cludge. Instead of
- trying to follow all of the normal DDE protocols, I just tried to force my
- commands on Program Manager without the proper acknowledgements. (Ok, so
- I'm a little lazy.) This was only partially successful and I soon broke
- down and went the whole nine yards. From my experience with it, I have only
- this to say: Follow the protocol. Don't try to force DDE down some
- applications neck, 'cause it's gonna puke.
-
-
-
-
-
-
- Since this article doesn't discuss DDE in general, I'm not going to go
- in depth about variations in DDE. That will be discussed in a later article
- by me or someone else (hopefully!). The way DDE with Program Manager works
- is something like this. You put together a string of commands and place
- them in a globally allocated space. A typical Program Manager command is:
- [CreateGroup(My Group)] You then send a WM_DDE_EXECUTE command to Program
- Manager and pass it the handle of your globally allocated string. That's
- about all there is, in theory. In practice, there's a lot that needs to be
- done.
-
- The segment of DDE code provided with this issue is called PMDDE.C.
- This contains routines which will be called by the main program, so it
- isn't a runable module in itself. It can be included with your own
- programs, however. Additionally, since I haven't finished the entire
- program yet, there's no way to be sure that it all works. Well, that's just
- a little splash of real life. If it doesn't work when I'm done, then I'll
- just have to fix it and provide any fixes required. I debated whether to do
- this article now or wait until I had the whole program together, but I
- decided that even if there are mistakes, the algorithm itself is still
- valid, and the final product will work.
-
- The best way to handle a DDE conversation is to create a window that's
- sole purpose is to handle your DDE conversation. In our case, and in most,
- the window that handles the DDE conversation is not the main window and it
- is usually not a window in the sense that it's visible. It is simply the
- procedure which handles the DDE messages that we want. In our case we'll
- call this procedure the DDEWndProc. The creation of this window is handled
- in the main program, but I'll give you an idea of what the code looks like.
-
- /* This code is executed when the main windows procedure
- receives the WM_CREATE message
- wc is a WNDCLASS variable.
- hDDEProc is a static HWND */
-
- wc.style = 0;
- wc.lpfnWndProc = DDEWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = "DDEWndProc";
-
- RegisterClass(&wc);
- hDDEProc = CreateWindow("DDEWndProc", NULL, WS_CHILD,
- 0, 0, 0, 0 hWnd, NULL, hInstance, NULL);
-
- if (!hDDEProc)
- MessageBox(hWnd, "DDE Window won't come up.", "ERROR",
- MB_OK);
- That's all there is to creating this blank little window. The next
- thing on our list is to handle the actual DDE conversation.
-
- Under the WM_CREATE of our DDEWndProc procedure, we need to add two
- global atoms. These are the Application and Topic names that our
- conversation is supposed to deal with. When you start a DDE conversation
- and you want to contact a DDE server application (Program Manager in this
- case) so you need to use the Application and Topic. Essentially what you do
-
-
-
-
-
-
- is send a WM_DDE_INITIATE message with the application and topic as a
- parameter. (These are actually one parameter by passing the
- MAKELONG(Application, Topic) as a long in the message parameter. You also
- need to pass the handle for your DDEWndProc in this message so that Program
- Manager will know how to get back in touch with us. Notice that the
- SendMessage has a -1 for the first parameter. This tells Windows to
- essentially broadcast the message to all programs that are running.
-
- The DDEWndProc will handle several other messages. One of them is the
- WM_DDE_ACK message. This message is used to acknowledge responses from the
- DDE server (Program manager.) This part is not quite so intuitive as I
- learned. First of all, this part has to be broken up. If you're
- acknowledging the WM_DDE_INITIATE (which we sent first thing. Don't tell me
- you already forgot what I wrote in the last paragraph!) Ok, so here we are
- sitting around with nothing to do and BOOM, we get an acknowledgement from
- our WM_DDE_INITIATE. Well, it's about time. So the first thing we want to
- do is make sure we grab the handle of Program Manager. This is passed as
- the wParam of the WM_DDE_ACK message sent by Program Manager in reply to
- our WM_DDE_INITIATE message. With all of the other messages we send to
- Program Manager, we will now know exactly who to send them to and not have
- to broadcast all of our messages.
-
- At this point I'd like to mention one thing about DDE. There are two
- ways to send Windows messages. You can use the SendMessage or the
- PostMessage procedures. Both functions do the same thing except with
- SendMessage, the message is sent and execution stops until the receiver of
- the message has finished processing the message. With PostMessage, control
- returns to the calling program immediately. With DDE you use the
- SendMessage only for the WM_DDE_INITIATE message. For all other messages
- you use the PostMessage procedure.
-
- In our DDEWndProc we need to handle the WM_DDE_ACK message. This is
- sent by Program Manager in response to all of our messages. We're actually
- going to break that process into two parts, though. The first WM_DDE_ACK
- that we get is in response to our WM_DDE_INITIATE. When we get the
- acknowledgement we then have to make sure that Program Manager will handle
- our conversation. We also need to grab Program Manager's handle.
- Additionally, the lParam of each WM_DDE_ACK is probably going to have some
- data that it points to that we need to delete. In the WM_DDE_INITIATE
- response the handles for two atoms are sent back to us. In this case, they
- happen to be the same two atoms we sent, so we just delete them. In
- response to our WM_DDE_EXECUTE messages, we get a Global Memory handle that
- is also the same one we sent to Program Manager (you'll see this later) so
- we have to free it.
-
- That basically handles all the rough stuff. To send commands to
- Program Manager we need to use the GlobalAlloc command with the
- GMEM_DDESHARE option so that we can share the data with Program Manager.
- The data is actually just text strings that we pass to Program Manager to
- execute as commands. These are commands like CreateGroup, AddItem, etc..
- The commands we'll use are:
-
- * CreateGroup(Group Name[, Group Path])
-
- Where Group Name is the name of the Program Group you want to add to
- Program Manager. Group Path is optional and specifies the path of the group
- file. In our case, we'll let program manager decide where to put that.
-
- * AddItem(Program [, Program Name, IconPath, IconNum, X, Y, DefDir, HotKey,
- Minimize]
-
-
-
-
-
-
- Just adds an Program item to the group you've created. The Program is
- that Path and the Filename of the executable. Program Name is the name you
- want to give it under Program Manager. Those are the only two we're going
- to cover for now.
-
- The other messages we're going to handle is the WM_CREATE_PMGRP and
- WM_ADD_ITEM. These are custom messages that we're going to define in our .h
- file. The first is used to create the program group under Program Manager
- and the second is going to be create any items we're putting in the program
- group. The lParam of these messages is going to be a handle for Atoms that
- are going to have the names of the program group and the file names.
-
- We'll then create the entire string that we want like:
- "[CreateGroup(New Group)][ShowGroup(New Group)]"
- and pass this off to Program Manager with a WM_DDE_EXECUTE message. Notice
- that all commands are in brackets. Don't know why but just use 'em.
-
- That about covers the PMDDE.C. I might modify it before the fourth
- article in this series, but if I do I'll pass it along.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Implementing a Linked List in the Global Heap
- By Mike Wallace
-
- The ability to implement a linked list is almost a requirement if a
- platform wants to get taken seriously. If you don't know what a linked
- list is, let me explain. Using an array to store data internally is fine
- if you have a good idea of how many items you'll need to store, which will
- determine the size of the array (which must be stated explicitly in your
- code prior to compiling). However, if you don't have a reasonable upper
- bound, you have two solutions: either make the array as large as possible
- and hope it always works, or allocate memory dynamically. The first
- solution isn't good enough. It usually means a lot of wasted memory, and
- in Windows, that's memory you can't afford to lose. The second solution is
- a bit more difficult to implement, but is the only way to go. By
- allocating memory dynamically (that is, at run-time), you only allocate
- exactly enough memory needed to hold your data. This is the method that
- produces a linked list, so called because the data is stored in a "list" of
- memory blocks (nodes), where each block holds an item of data plus another
- field giving the memory location of the next node in the "list", thus
- "linking" the data.
-
- I recently had to implement a linked list for a Windows program but
- could not find any good examples of how to do this, so I had to reason the
- problem out. It turned out to not be as difficult as I expected, but there
- are some things you need to keep in mind when implementing a linked list.
- Microsoft advises that when allocating a memory block, make it moveable and
- discardable. Why? Windows is more efficient if it can move your memory
- block around while the program is running in order to make the most of the
- available memory. However, a consequence of this is that you cannot use a
- pointer when linking two consecutive nodes in the list because Windows can
- (and will) move each node around in memory as it sees fit. So, I had to
- use a handle since that would guarantee the address stored in it (for the
- next node) would always be valid. The tricky part was that Windows
- requires a memory block to be locked when accessing a node by handle
- because that ensures the node won't be moved until you unlock the block.
-
- At the end of this article I've included the source code for a routine
- which allocates ten nodes in the global heap, stores in each node a number
- between 1 and 10 (the numbers are stored consecutively), then traverses the
- list and prints (to a file) the value stored in each node, and finally,
- retraverses the list and frees each node one at a time. Included with the
- Windows Programmer's Journal package is all the code and files needed to
- run the program. All of the files have a filename of "linklist", except
- the batch file which is run to compile the program, which is called
- "makelist.bat".
-
- The beginning of the function contains declarations for the variables
- needed to implement the linked list. The _listmarker structure is the
- structure of each node in the list. The LISTMARKER variable has to be a
- FAR pointer to the structure since the function uses the global heap. The
- LISTMARKER variables (tailPos, tempPos and headPos) are used to traverse
- the list. Finally, "fp" is a file pointer to the output file.
-
- After the function opens the output file for writing, it does a
- GlobalAlloc to allocate a block on the global heap for the first node. If
- "NULL" is returned, it means there was not enough room for the node of a
- size of FileMarker, so the function displays a message to that effect and
- returns to the calling routine. Otherwise, the allocated block is locked
- (so the block doesn't move while its fields are getting assigned), gets
- initialized and then gets unlocked. The "hMem" handle points to the first
-
-
-
-
-
-
- node for the duration of the function. This algorithm is repeated for each
- successive node, using tailPos to point to the current end of the list.
-
- The function then traverses the linked list, printing out the value of
- the "value" field to the output file. This is done by locking each node,
- performing a "fprintf" on the "value" field and then unlocking the node.
- The output file is then closed.
-
- Finally, the function traverses the list, freeing each node one at a
- time. This is done by locking each node, saving its handle to the next
- node, unlocking the current node and then freeing it. This algorithm is
- repeated until the list has been traversed.
-
- That is the entire algorithm. This is the first time I have written a
- linked list in Windows, so there may be more efficient methods of attaining
- the same ends. If you can find any, please send in your suggestions and
- we'll print them.
-
-
- void FAR PASCAL MakeList (HWND hWnd)
- {
- /* local variables */
- short i;
- static HANDLE hMem, hMem2, hMem3;
-
- /* structure of each node in linked list */
- typedef struct _listmarker {
-
- short value;
- HANDLE next;
-
- } ListMarker;
-
- /* declare a far pointer to the above structure */
- typedef ListMarker FAR *LISTMARKER;
-
- LISTMARKER tailPos, tempPos, headPos;
-
- /* pointer to output file */
- FILE *fp;
-
- /* Open output file for writing */
- fp= fopen("data.out", "w");
-
- /* Build initial linked list of the numbers 1 to 10 */
- if((hMem= GlobalAlloc(GMEM_DISCARDABLE | GMEM_MOVEABLE,
- sizeof(ListMarker))) == NULL) {
-
- /* Not enough memory, so beep, show a message and return */
- MessageBeep(0);
- MessageBox(hWnd, "Out of allocation memory!", "ERROR", MB_OK);
-
- return;
-
- }
-
- /* Lock the first node, save a value, set next to NULL and unlock */
- tailPos= headPos= (LISTMARKER) GlobalLock(hMem);
- headPos->value= 1;
- headPos->next= NULL;
-
-
-
-
-
-
- GlobalUnlock(hMem);
-
- /* Allocate a node for each of the numbers between 2 and 10 and link */
- for (i=2; i < 11; i++) {
-
- /* setup index lookup lists */
- if((tailPos->next= GlobalAlloc(GMEM_DISCARDABLE | GMEM_MOVEABLE,
- sizeof(ListMarker))) == NULL) {
-
- MessageBeep(0);
- MessageBox(hWnd, "Out of allocation memory!", "ERROR",
- MB_OK);
-
- return;
-
- } /* If - End */
-
- /* Lock the next node, save the value, and set its next to NULL
- */
- hMem2= tailPos->next;
- tempPos= (LISTMARKER) GlobalLock(hMem2);
- tailPos= tempPos;
- tailPos->value= i;
- tailPos->next= NULL;
-
- GlobalUnlock(hMem2);
-
- } /* While - End */
-
- /* Lock the 1st node and write out its "value" field */
- tailPos= headPos= (LISTMARKER) GlobalLock(hMem);
- fprintf(fp, "%d\n", tailPos->value);
-
- /* Save the handle to the next node */
- hMem2= tailPos->next;
-
- /* Unlock the 1st node */
- GlobalUnlock(hMem);
-
- /* Go through list and print out "value" until no more nodes */
- while (hMem2 != NULL) {
-
- /* Lock the next node and save to tailPos */
- tempPos= (LISTMARKER) GlobalLock(hMem2);
- tailPos= tempPos;
-
- fprintf(fp, "%d\n", tailPos->value);
-
- /* Get the handle to the next node and then unlock the current one */
- hMem2= tailPos->next;
- GlobalUnlock(hMem2);
-
- } /* While - End */
-
- /* Close the output file */
- fclose(fp);
-
- /* free nodes in the list */
- tempPos= (LISTMARKER) GlobalLock(hMem);
- hMem2= tempPos->next;
-
-
-
-
-
-
- tempPos= (LISTMARKER) GlobalLock(tempPos->next);
- GlobalUnlock(hMem);
- GlobalFree(hMem);
-
- while(tempPos->next != NULL) {
-
- hMem3= tempPos->next;
- tempPos= (LISTMARKER) GlobalLock(tempPos->next);
- GlobalUnlock(hMem2);
- GlobalFree(hMem2);
- hMem2=hMem3;
-
- }
-
- GlobalUnlock(hMem2);
- GlobalFree(hMem2);
-
- return;
-
- } /* MakeList */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Book Reviews
- By Pete Davis
-
-
- Undocumented Windows: A Programmer's Guide to Reserved Microsoft Windows
- API Functions
-
- by Andrew Schulman, David Maxey, and Matt Peitrek
- Addison-Wesley Publishing Company
- ISBN 0-201-60834-0
-
-
- Well, away with the formality and on to the book review. If you're
- comfortable with programming Windows, then I have only two words to you
- regarding this book: BUY IT! This is the one of the best references, not
- only for finding functions that Microsoft 'forgot' to tell us about, but it
- also gives an incredible amount of insight into how the internals of
- Windows operates. Not to take away from Maxey and Peitrek, but Schulman's
- fingerprints are all over this book.
-
- This book is very well organized. Each chapter is divided in a way
- that's easy to understand and covers specific topics. It's hard to know
- where to start with this book, it has it all. It has chapters on KERNEL,
- USER, GDI, and SYSTEM calls. It has a chapter on undocumented Windows
- messages. There are great chapters on how to disassemble and examine
- Windows executables. This is particularly useful for the true Windows
- hacker.
-
- The book also comes with a load of utilities for examining Windows
- executables. I have actually found several of these utilities useful simply
- for debugging my own code. Some of the utilities will tell you what
- undocumented calls a program is making. This is a neat little way to find
- out who's got an inside track at Microsoft. Of course, with the release of
- Undocumented Windows, many of these calls are going to be used more
- frequently.
-
- Microsoft's humor in naming some of these calls (e.g. BozosLiveHere
- and TabTheTextOutForWimps) are accented with the authors' humor. When
- discussing how a certain utility sometimes "decides that a function is
- undocumented when in fact it's documented. (It's sort of like one's
- coworker who every week thinks he's found a bug in the compiler)." The book
- is a joy to read just for the humor alone.
-
- Although there are a lot of functions listed (well over a hundred, I'd
- guesstimate), the true value of this book lies in its discussion of Windows
- and how Windows operates. There is more in this book on the internal
- operations of Windows than any ten books I've seen. He also discusses at
- length the politics at Microsoft regarding the undocumented functions.
-
- Well, I've talked about all the reasons that I like the book, but
- let's discuss it's usefulness. Is it useful? Well, for its in-depth
- discussion of Windows internals, yes. The functions themselves are
- scattered in a lot of different areas of programming. Some would be useful
- to some people while others would be useful to others. For example, someone
- working on a Windows debugger would be very interested in task queues and
- the like whereas a programmer of a painting package might be more
- interested in the GDI function calls. There are tons of functions and the
- documentation of each one is more complete than the documentation Microsoft
- provides for most of it's 'documented' functions.
-
-
-
-
-
-
-
- Schulman and Co. have done a fantastic job on this book and I don't
- think I could give it a higher recommendation. I look forward to his
- Undocumented NT (maybe? perhaps?).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Last Page
- By Mike Wallace
-
- Well, it's happened.
- The first issue of Window's Programmer's Journal (official motto:
- Apply directly to infected areas) is done, and I feel good about it. Why?
- Because it's the first magazine I've seen that is fully devoted to Windows
- programming and it's more than just product reviews. Pete and I were
- hungry for something like WPJ but couldn't find anything that was really
- helpful, so we thought, "Let's do one ourselves." It's been fun so far,
- and hopefully we'll get lots of articles from ya'll so we can fill each
- issue with solutions to your Windows programming problems. If you think
- you have an idea for an article, send it in! If you just want to submit an
- outline for an article to see if we'd be interested before you write a full
- article, do it! The magazine can't last long without help from you people,
- and if you've done something cool in Windows, we want to hear about it! If
- you have any questions about Windows, ask! We're going to start a letters
- column as soon as we have enough letters to fill one, and if we can't
- answer your questions, we'll submit them to the rest of our readers to get
- an answer. We're not just doing this as part of our work-release program,
- we want to learn everything we can about programming in Windows, and I
- haven't seen any magazines that are as devoted to it as I'd like, and we're
- not looking for articles written by people with Ph.D.s - we'll take an
- article from anybody. Future issues will depend on it.
-
- Speaking of future issues, we have a few ideas about what you'll see
- soon. Pete's going to write an article about how to print under Windows
- 3.0 & 3.1, we'll continue our beginner's column, start a column on how to
- program C++ (written by me - since I don't know anything about C++, I
- seemed overly qualified to write a beginner's column on it), some product
- reviews of books and software, and just yesterday I bought a Windows NT
- workstation and Pete has the pre-release of NT, so we're going to tell you
- all about that and try to write some programs for it.
-
- Coming Soon! The WPJ BBS! By Jan. 1st (if we're lucky, and by the
- 5th if we're not quite so lucky), you can send your articles and letters
- directly to us. We also plan on putting the SIMTEL20 CD-ROM on it so you
- can download anything you want. It's a great CD full of stuff you never
- knew you needed but can't live without once you get it. We'll also be
- getting the CICA CD-ROM of Windows shareware and public domain software
- soon. See the "How to get in contact with us" section elsewhere in this
- issue for more info.
-
- If you're wondering about the point of this column, this is where I
- get to rant and rave about anything I'd like. If you don't want to read
- it, don't. You won't miss anything of earth-shattering importance. I'll
- try to make it interesting, but there's no telling what will happen here -
- you'll have to wait and see. If there's anything on your mind you want to
- talk about it, send me a note and if it sounds like it would be of interest
- to other readers, I'll write what I can about it. This is your forum as
- much as mine. One of my minors in school (Va. Tech, by the way - I
- graduated in '89 with a BS in Computer Science) was philosophy (the other
- was math - I knew you were wondering about that!), so just because I don't
- know anything about a subject won't stop me from writing about it. If
- there's anything you want to get off your chest, tell me about it. I'm
- always looking for a good discussion about anything.
-
- That's the first issue. Hope you liked it; hope we're around for
- awhile. This could be a lot of fun, and we want you to join us. Until
- next month, may you look like the late Totie Fields!
-
-
-
-
-
-
- Getting in touch with us:
-
-
- Right now there are only four ways to get in touch with us. If you
- have access to the Internet or BITNET, you can get in touch with us at:
-
- HJ647C at GWUVM.GWU.EDU -or- HJ647C at GWUVM.BITNET (both Pete)
-
- CompuServe: 71141,2071 (Mike)
-
- WPJ BBS (703) 503-3021
-
- You can also send paper mail to:
-
- Windows Programmer's Journal
- 9436 Mirror Pond Drive
- Fairfax, VA 22032
- U.S.A.
-
-
- Also, around January 1st, we'll be setting up a BBS specifically to
- support the WPJ, but we'll also be offering the SIMTEL20 CD-ROM for
- downloads. The SIMTEL20 system is one of the largest sources of public
- domain and shareware software. We'll also be adding more CDs later as we
- can afford it.
-
- Anyway, the Windows Programmer's Journal BBS can be reached at: (703)
- 503-3021. You can get in touch with either Mike or Pete at this number. The
- BBS is going to be relatively new, so don't be surprised if it's a little
- buggy in the beginning. Right now it's only 2400 baud as my 9600 baud modem
- died on me, but in the first month or two you can expect it to go up to
- 14,400. You can also expect to see a Fido-net node address by the second
- issue.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-