]]>译-C++最单的windowsE序 The Simplest Windows Programhttp://www.shnenglu.com/k71983/archive/2008/09/23/62560.html聂元?/dc:creator>聂元?/author>Tue, 23 Sep 2008 03:01:00 GMThttp://www.shnenglu.com/k71983/archive/2008/09/23/62560.htmlhttp://www.shnenglu.com/k71983/comments/62560.htmlhttp://www.shnenglu.com/k71983/archive/2008/09/23/62560.html#Feedback4http://www.shnenglu.com/k71983/comments/commentRss/62560.htmlhttp://www.shnenglu.com/k71983/services/trackbacks/62560.html
来自Qhttp://www.relisoft.com/win32/winnie.html
译:(x)聂元?
1. The Simplest Windows Program
1.最单的WindowsE序
Before you can even begin thinking about programming in Windows, you have to be able to understand how this simple program works.
在你开始想如何在windows下编E之前,你必要弄清楚下面这个简单windowsE序的工作原理?
Windows API calls are highlighted in blue and Windows specific data types are shown in green. I will also usually put a double colon in front of API calls. In C++, that simply means that I'm calling a global function, in case there is some ambiguity.
Sources (zipped file 4k) are right here. Remember to compile them as a Windows application. For instance, in Visual C++ select File.New.Projects.Win32 Application. Otherwise you'll get the error: unresolved external _main. (I provided project file Winnie.dsp for those of you who use MS VC++ 6.0 and Winnie.sln for the users of VC++ 7.0)
First, in a Windows program, you have to define a Window Class, the "class" of window(s) that will be displayed by your application (not a C++ class). In our case we will display only one window, but still, we need to give Windows some minimal information about its Class. The most important part of the WinClass (now, that's a C++ class that describes the Window Class) is the address of the callback procedure, or the Window Procedure. Windows is supposed to call us--Windows sends messages to our program by calling this procedure.
Notice the declaration of WindowProcedure. Windows calls it with a handle to the window in question, the message, and two data items associated with the message, the paramters, WPARAM and LPARAM.
In WinClass we also have to specify things like the program instance handle HINSTANCE, the mouse cursor (we just load the standard arrow cursor), the brush to paint the window's background (we chose the default window color brush), and the symbolic name of our class (you don't have to understand the meaning of all those yet).
#include <windows.h>
LRESULT CALLBACK WindowProcedure
(HWND hwnd, unsigned int message, WPARAM wParam, LPARAM lParam);
class WinClass
{
public:
WinClass (WNDPROC winProc, char const * className, HINSTANCE hInst);
void Register ()
{
::RegisterClass (&_class);//now we don’t deal with the error
}//we will process the error in the next version
private:
WNDCLASS _class;//define a private WNDCLASS object member
};
WinClass::WinClass
(WNDPROC winProc, char const * className, HINSTANCE hInst)
{
_class.style = 0;
_class.lpfnWndProc = winProc; // window procedure: mandatory
_class.cbClsExtra = 0;
_class.cbWndExtra = 0;
_class.hInstance = hInst; // owner of the class: mandatory
_class.hIcon = 0;
_class.hCursor = ::LoadCursor (0, IDC_ARROW); // optional
_class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // optional
_class.lpszMenuName = 0;
_class.lpszClassName = className; // mandatory
}
Once the Window Class is registered, we can proceed with the creation of a window. This is done by calling the CreateWindow API. It takes a lot of arguments: the name of the window class that we have just registered, the caption that will appear in the title bar, window style, position, size, and the application instance. The rest of the arguments, for the time being, will be left equal to zero.
This part of the program can also be encapsulated into a C++ class, WinMaker.
E序的这部分也被我封装到了一个C++的类WinMaker当中?
The window will not appear on the screen until you tell Windows to show it.
q你创建好了窗口,但你q是看不刎ͼ你必调用ShowWindow函数让它昄?
class WinMaker
{
public:
WinMaker (): _hwnd (0) {}
WinMaker (char const * caption,
char const * className,
HINSTANCE hInstance);
void Show (int cmdShow)
{
::ShowWindow (_hwnd, cmdShow);
::UpdateWindow (_hwnd);
}
protected:
HWND _hwnd;
};
WinMaker::WinMaker (char const * caption,
char const * className,
HINSTANCE hInstance)
{
_hwnd = ::CreateWindow (
className, // name of a registered window class
caption, // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // x position
CW_USEDEFAULT, // y position
CW_USEDEFAULT, // witdh
CW_USEDEFAULT, // height
0, // handle to parent window
0, // handle to menu
hInstance, // application instance
0); // window creation data
}
A Windows program is event-driven. It means that you, as a programmer, are supposed to be on the defensive. The user will bombard Windows with various input actions, and Windows will bombard your program with messages corresponding to these actions. All you have to do is to respond to these messages. The picture below shows schematically how it works.
Windows gets various events from the keyboard, the mouse, the ports, etc. Each event is quickly converted into a message. Windows (the operating system) dispatches messages to appropriate windows. For instance, all keyboard messages go to the window that currently has the input focus (the active window). Mouse messages are dispatched according to the position of the mouse cursor. They usually go to the window that is directly under the cursor (unless some program captured the mouse).
All these messages end up in message queues. Windows keeps a message queue for every running application (actually, for every thread). It is your duty to retrieve these messages one-by-one in what is called a message loop. Your program has to call GetMessage to retrieve a message. Then you call DispatchMessage to give it back to Windows. Couldn't Windows just go ahead and dispatch all these messages itself? In principle it could, but a message loop gives your program a chance to have a peek at them and maybe perform some additional actions before dispatching them. Or not...
Each message is addressed to a particular window. When you tell Windows to dispatch such a message, it will figure out the class of this window, find the associated Window Procedure, and call it. Every single message sent to our window will end up in our window procedure. It is now up to us to respond to it. So, do we have to respond appropriately to every possible type of Windows message? There a hundreds of them! Fortunately, no! We only need to intercept those messages that we are interested in. Everything else we pass back to Windows for default processing using DefWindowProc.
Let's have a look at WinMain. The execution of a Windows program doesn't start in main--it starts in WinMain. In our WinMain, we create a WinClass and register it. Then we create an actual window (of the class we've just registered) and show it. Actually, WinMain is called with the appropriate show directive--the user might want to start the application minimized or maximized. So we just follow this directive. Next, we enter the message loop and keep retrieving and dispatching messages until GetMessage returns 0. At that point the message's wParam will contain the return code of the whole program.
MSG msg;
int status;
while ((status = ::GetMessage (& msg, 0, 0, 0)) != 0)
{
if (status == -1)
return -1;
::DispatchMessage (& msg);
}
return msg.wParam;
}
The GetMessage API is an interesting example of the bizarre Microsoft Troolean (as opposed to traditional, Boolean) logic. GetMessage is defined to return a BOOL, but the documentation specifies three types of returns, non-zero, zero and -1. I am not making it up! Here's an excerpt from the help file:
· If the function retrieves a message other than WM_QUIT, the return value is nonzero.
· If the function retrieves the WM_QUIT message, the return value is zero.
· If there is an error, the return value is -1.
The other important part of every Windows program is the Windows Procedure. Remember, Windows will call it with all kinds of messages. All these messages can be ignored by sending them to DefWindowProc. There is only one message that we must intercept. That's the WM_DESTROY message that is sent by Windows when the user decides to close the window (by pressing the close button in the title bar). The standard response to WM_DESTROY is to post the quit message and return zero. That's all there is to it.
#defineSTART_POS1 #defineRACE_DISTANCE70// the distances of the race
#defineTORTOISE 'T' // the symbol that is printed in the screen as a tortoise #defineRABBIT 'R' // the symbol that is printed in the screen as a rabbit #defineROAD '.' // the symbol that is printed in the screen as a mile road. #defineCOMPLETE_ROAD '+'
//get the speed of the tortoise or the rabbit intGetTortoiseSpeed(intpercent, int * speed); intGetRabbitSpeed(intpercent, int * speed);
//output the result in console interface voidPrintRaceResult(inttortoisePosition, intrabbitPosition);
intmain(void) { intpercent; // save the percent as a integer that less 10 // 1 10%, 2 20%, 9 90%, 10 100% etc. intspeed; // save the speed of the rabbit or the tortoise
//compute next rate of rabbit speed percent = rand()%10 + 1; //get the percent
if( !GetRabbitSpeed(percent, &speed))//get the speed of rabbit { puts("Error!\n"); exit(ERROR); }
//move the rabbit rabbitPosition = rabbitPosition + speed;
//check the position whether is right or not, then correct it. if(rabbitPosition < 0) rabbitPosition = START_POS; elseif(rabbitPosition > RACE_DISTANCE) rabbitPosition = RACE_DISTANCE;
//show the tortoise and the rabbit PrintRaceResult(tortoisePosition, rabbitPosition);
}
//print the race result if(rabbitPosition > tortoisePosition) { printf("Rabbit Wins!\n"); } elseif(rabbitPosition == tortoisePosition) { printf("It's a tie\n"); } else { printf("Tortoise Wins!\n"); }
http://www.functionx.com/win32/ This site's goal is to provide a few lessons on Win32 programming. Keep in mind that everything you can do with Win32 using a C++ compiler
Icons by FastIcon.com: This artist has 41 icon sets containing 657 total icons for Mac OS X listed on InterfaceLIFT. The sets are shown in order of popularity.
VistaIcons.com is a collection of free Vista Style icon sets of over 2500 high quality icons in png and ico format. From VistaIcons.com you can freely download 256×256 PNG icons for Windows Vista
It is apersonal site and web playground of Birmingham (UK) based developer Mark James. There are many sets of icon for free download include silk web icons, flag icons…
IconBuffet is home to a tasty plethora of free icons. Collect them, download them, trade them with your friends. They’re kinda like baseball cards, only without the steroids. And you can use them on your website.
InterfaceLIFT is your source for graphical user interface enhancements for Mac OS X, Microsoft Windows, and Linux. They specialize in desktop wallpaper, icons, themes, and news with a focus on community. New content is posted virtually every day.
Here you´ll find the best icons from the best artists in the world. The icons here listed belong to the individual authors and companies. They are free for personal and non commercial use. If you are an icon artist and desire to share your work with the world, this is your place. Just click on the submit menu and follow the easy steps to add your icons.
A list of 90 icon packs that you can download for free. (include Vista High PX, Office Space Icon Set for Windows Vista, iVista Icon Pack, iVista Icon Pack 2, XP Icons,Royalty Free Icons for Toolbar and Web,Friendly Fire Icon Pack,Yoritsuki Icons,Antique Icons,Vista Glass Folder Icons,Arzo Icons Vol. 1,Gaming Icons Pack,Mario Galaxy Luma Icons,Christmas Icons,Wifun Icons by Rokey,Grzanka’s Icons,Fantastic Dream by Rokey,Eico 1 year by Rokey,128×128 Icons Set 5,Antares Iconset,Perfect Fanstasy,Monster Icons,128×128 Icons Set 4,iMac Icons,Camino Icons,Nes Icons Pack,iLife and iWork ‘08 Icons,Mouse Category Season 03 etc…)
intmain(void) { charfirst[MAX]; charlast[MAX]; charformal[2 * MAX + 10]; doubleprize;
puts("Enter your first name: "); gets(first); puts("Enter your last name: "); gets(last); puts("Enter your prize money: "); scanf("%1f", prize); sprintf(formal, "%s, %-19s: $%6.2f\n", last, first, prize); puts(formal);