Tutorials to .com

Tutorials to .com » Software » Asm » WIN32 compilation: 3. To create a simple window

WIN32 compilation: 3. To create a simple window

Print View , by: iSee ,Total views: 11 ,Word Count: 4830 ,Date: Wed, 20 May 2009 Time: 12:37 AM

The third class to create a simple window


In this lesson we will write a Windows program that will display a standard desktop window.

Theory:

Windows program, in writing graphical user interface need to call a large number of standard Windows Gui function. In fact, this is for users and programmers will be beneficial for the users, are faced with a window with a set of criteria, the operation of these windows are the same, so the use of different applications are not required to re-learning how to operate. To the programmer, these are all the source code Gui After Microsoft's rigorous testing can be used at any time used. As of course procedures specifically for programmers to write or difficult. In order to create a window-based applications, must be in strict compliance with the norms. This is not difficult to do, as long as the use of modular or object-oriented programming methods can be.

I will list below shows a window on the desktop a few steps:

  1. Get your applications handle (necessary);
  2. Get command line parameters (if you want to get from the command line parameters, optional);
  3. Register window class (required, unless you are using Windows predefined window class, such as the MessageBox or dialog box;
  4. Have a window (necessary);
  5. Display window on the desktop (required unless you do not want to show it immediately);
  6. Refresh the window client area;
  7. Unlimited access to the window to enter the news cycle;
  8. If there is the news arrived, in charge of the window from the window callback function to deal with;
  9. If the user close the window to withdraw from the deal.

Opposed to the single-user programming under DOS is, Windows the procedure under the framework of the structure is quite complex. However, Windows and DOS in the system architecture is completely different. Windows is a multi-tasking operating system, so the system at the same time collaboration between multiple applications running. This requires Windows programmers programming must be in strict compliance with the norms, and to develop good programming style.

Content:

The following is our simple window program's source code. Enter the complex in the details, I will make a few points outline the main points:

  1. You should take into account the proceedings of all constants and the structure of the statement in a header file, and the beginning of the source code contains the header files. Doing so will save you a lot of time, but also time and again to avoid. At present, the most comprehensive document is the first written hutch, hutch, or you can go to my website. You can also define your own constants and structure, but it put them in a separate header file
  2. Includelib with instructions, including the procedures you need to invoke the library file, for example: If you want to call the procedure "MessageBox", you should be in the source file to add the following line: includelib user32.lib statement tells MASM that your program will be used some of the introduction of the Treasury. If you quote more than a library, a simple statement includelib to join, do not worry linker how to deal with so many libraries, as long as the link when the link switch / LIBPATH to specify the path where your database.
  3. In other parts of the document using the first definition of function prototypes, constants and structures, it is necessary to maintain and strictly defined in header files, including sensitive. Function in the query definition, which will save you a lot of time;
  4. At compile, link documents with makefile, replacing knock repeat button.

.386
. model flat, stdcall
option casemap: none
include \ masm32 \ include \ windows.inc
include \ masm32 \ include \ user32.inc
includelib \ masm32 \ lib \ user32.lib; calls to functions in user32.lib and kernel32.lib
include \ masm32 \ include \ kernel32.inc
includelib \ masm32 \ lib \ kernel32.lib

WinMain proto: DWORD,: DWORD,: DWORD,: DWORD

. DATA; initialized data
ClassName db "SimpleWinClass", 0; the name of our window class
AppName db "Our First Window", 0; the name of our window

. DATA?; Uninitialized data
hInstance HINSTANCE?; Instance handle of our program
CommandLine LPSTR?
. CODE; Here begins our code
start:
invoke GetModuleHandle, NULL; get the instance handle of our program.
; Under Win32, hmodule == hinstance mov hInstance, eax
mov hInstance, eax
invoke GetCommandLine; get the command line. You don''''t have to call this function IF
; Your program doesn''''t process the command line.
mov CommandLine, eax
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT; call the main function
invoke ExitProcess, eax; quit our program. The exit code is returned in eax from WinMain.

WinMain proc hInst: HINSTANCE, hPrevInst: HINSTANCE, CmdLine: LPSTR, CmdShow: DWORD
LOCAL wc: WNDCLASSEX; create local variables on stack
LOCAL msg: MSG
LOCAL hwnd: HWND

mov wc.cbSize, SIZEOF WNDCLASSEX; fill values in members of wc
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground, COLOR_WINDOW +1
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, OFFSET ClassName
invoke LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
invoke RegisterClassEx, addr wc; register our window class
invoke CreateWindowEx, NULL, \
ADDR ClassName, \
ADDR AppName, \
WS_OVERLAPPEDWINDOW, \
CW_USEDEFAULT, \
CW_USEDEFAULT, \
CW_USEDEFAULT, \
CW_USEDEFAULT, \
NULL, \
NULL, \
hInst, \
NULL
mov hwnd, eax
invoke ShowWindow, hwnd, CmdShow; display our window on desktop
invoke UpdateWindow, hwnd; refresh the client area

. WHILE TRUE; Enter message loop
invoke GetMessage, ADDR msg, NULL, 0,0
. BREAK. IF (! Eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
. ENDW
mov eax, msg.wParam; return exit code in eax
ret
WinMain endp

WndProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM
. IF uMsg == WM_DESTROY; if the user closes our window
invoke PostQuitMessage, NULL; quit our application
. ELSE
invoke DefWindowProc, hWnd, uMsg, wParam, lParam; Default message processing
ret
. ENDIF
xor eax, eax
ret
WndProc endp

end start

Analysis:

See a simple Windows program that so many lines, you would like to withdraw a little bit? But you need to know is that the majority of the above template code is only the meaning of the template code which means almost all of these standard Windows program are the same. At the time of writing Windows programs you can copy the code to copy to, of course, these duplicate code also wrote a very good library. In fact, the real focus on the code to write in WinMain. This is the same number of c compilers, there is no need to care about other chores, focus on the WinMain function. The only difference is the C++ compiler requires that you have the source code must have a function called WinMain. Otherwise, C will not know which function before and after the code and related links. Relative C, assembly language provides greater flexibility, it does not force a function called WinMain.

The following analysis we begin, you can get mentally prepared to do a good job, this is not too easy for a living.

.386
. model flat, stdcall
option casemap: none

WinMain proto: DWORD,: DWORD,: DWORD,: DWORD

include \ masm32 \ include \ windows.inc
include \ masm32 \ include \ user32.inc
include \ masm32 \ include \ kernel32.inc
includelib \ masm32 \ lib \ user32.lib
includelib \ masm32 \ lib \ kernel32.lib

You can put the first three lines as a "must".

.386 Told MASN instruction set we are going to 80386.
. Model flat, stdcall tell MASM addressable memory used in our model can also be here to join our stdcall tell MASM to pass the parameters used in the agreement.

Next is the WinMain function prototype declares that because we will use the function, it must be a statement. We window.inc documents must be included, because it contains a large number of constants used in the definition and structure, the file is a text file, you can use any text editor to open it, window.inc also does not contain all the constants and structure definition, but in the hutch and I have been constantly adding new content. If you can not find the time being in window.inc, you can also join the.

We are stationed in the procedure call user32.dll (example: CreateWindowEx, RegisterWindowClassEx) and kernel32.dll (ExitProcess) of the function, it is necessary to link these two libraries. Then if I asked: what library you need to chain to your procedures? The answer is: first find the function you want to call what the Treasury, and then include it. For example: If you want to call a function in gdi32.dll, you must first file contains gdi32.inc. And MASM compared, TASM will be much simpler, you can introduce a library, that is: import32.lib. <Translator's Note: But the trouble is Tasm5 very windows.inc not comprehensive, but if all Windows.inc contains the definition of the API will be enough memory, so every time you have to copy the definition used by the API>

. DATA

ClassName db "SimpleWinClass", 0
AppName db "Our First Window", 0

. DATA?

hInstance HINSTANCE?
CommandLine LPSTR?

Followed by the DATA "sub." In. DATA, we defined at the end of two NULL string (ASCIIZ): in which Windows class name ClassName is, AppName is the name of our window. These two variables are initialized it. Not to initialize the volume on the two edges. DATA? "Subparagraph" in which representatives of hInstance handle applications, CommandLine save imported from the command line parameters. LPSTR is HINSTACE and two data types, and they are defined in header files, you can alias as a DWORD, the reason for such a re-entry only to easy. You can view windows.inc documents. DATA? The variables are not initialized, which means that in the process just starts what their value is irrelevant, but possession of a piece of memory, then you can re-use it.

. CODE
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke GetCommandLine
mov CommandLine, eax
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, eax
.....
end start

. DATA "sub" contains all your application code must have. Code and end Between. As for the name as long as the label to comply with norms and to ensure that Windows is the only specific name does not matter what it is. We process the first statement is a call to GetModuleHandle to find applications that we handle. In Win32, the application handle and module handle are the same. You can handle the examples as your application ID. We call it a number of functions are regarded as a parameter to pass, it will be at the beginning and maintained it can save a lot of things.

Pay particular attention to: WIN32 under the instance handle of your application is in memory of the linear address.

WIN32 in function if the function return value, it is to pass through the register eax. Other values can be entered by passing the parameters to the return address. A WIN32 function is called when the segment register will always keep and ebx, edi, esi and ebp registers edx and ecx, and the value is always uncertain and can not return to the application. Special Note: from the Windows API function return, eax, ecx, edx call of duty and not necessarily the same as before. When the function returns, the return value in eax on. If your application available to the Windows function call, we must also respect the fact that paragraph in the preservation of function at the entrance to register and ebx, esp, esi, edi and the value of the restoration of function return. If so, then your application will soon collapse. From your program to Windows to call a function in general, there are two: Windows window process and the Callback function.

If your application does not deal with the command line there would be no need to call GetCommandLine, here is just to let you know how to call If you want to do.

The following is the WinMain call. The function of a total of four parameters: the application instance handle, the application handle of the previous examples, command-line parameter string pointer and how to display window. Win32 does not handle the previous example of the concept, so the total second parameter to 0. The reason why it is to retain and Win16 compatibility considerations, in Win16, if hPrevInst is NULL, then the function is run for the first time. Special Note: You do not have to declare a WinMain function, in fact, in this context you can make decisions, you do not even have to have a WinMain function of the same. As long as your code of WinMain after Kaodao GetCommandLine, they achieved exactly the same function. WinMain return in the return code in eax on. And then the end of the application through the ExitProcess function of the return code passed to Windows.

WinMain proc Inst: HINSTANCE, hPrevInst: HINSTANCE, CmdLine: LPSTR, CmdShow: DWORD

Above is the definition of WinMain. Attention with the proc command in the parameter: type of the parameters of the form, they are passed by the caller of WinMain, we have cited is the parameter name can be used directly. As for push and retire the balance of the stack when the stack by MASM related compile-time in the pre-and post-order instructions to carry out the compilation sequence. LOCAL wc: WNDCLASSEX LOCAL msg: MSG LOCAL hwnd: HWND LOCAL pseudo-instruction in the stack for local variables in the allocation of memory space, all the LOCAL directive must be followed after the PROC. LOCAL variables followed by a statement in the form of variable name: variable type . For example, LOCAL wc: WNDCLASSEX tell MASM that is, wc name is for the local side of the volume of distribution in the stack length is the length of the structure WNDCLASSEX memory space, and then we use the local variables is not necessary to consider the issue of the stack, taking into account under DOS compilation, which say that it is a gift. But this requires such a local variable declared in the function of the end of the release of stack space, (which can not be cited in the in vitro function), another drawback is that you can not initialize due to the local variables you have to at a later date for additional its assignment.

mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground, COLOR_WINDOW +1
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, OFFSET ClassName
invoke LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax invoke
RegisterClassEx, addr w

Above a few lines from the concept that is very simple indeed. As long as a few lines of instructions can be achieved. The main concept is the window class (window class), a window is a window-type norms, the norms in the definition of a number of major elements of the window, such as: icon, cursor, background color, and is responsible for handling the window function. When you have a window must be of such a window class. If you want to have more than one same type of window, the best way is to store up the window class, this method can save a lot of memory space. Perhaps you do not feel too much, but look at the majority of PC memory 1M only when doing so is necessary. If you want to define your own window class must be created: WINDCLASS or in a specified WINDOWCLASSEXE structure elements of your window, and then call RegisterClass or RegisterClassEx, again according to the window have a window class. Characteristics of different window of the window must be defined in different categories. WINDOWS There are several predefined window class, such as: buttons, edit boxes and so on. To produce the styles of the window do not have pre-defined window class again, and as long as the package type of pre-defined class name as a parameter to CreateWindowEx call.

WNDCLASSEX a member of the most important is the lpfnWndProc. Lpfn that the members of the prefix is a long pointer to function. In the Win32 memory model is due to FLAT-type, there is no difference between near or far. Each window class must have a window of the process, when belonging to a specific Windows message window to the window, the window of the window class, which deals with all the news, such as keyboard or mouse message news. As a result of the process window intelligently handled almost all the windows message loop, so you can join the message in which the process can be. Now I will have to explain each and every member of the WNDCLASSEX

WNDCLASSEX STRUCT DWORD
cbSize DWORD?
style DWORD?
lpfnWndProc DWORD?
cbClsExtra DWORD?
cbWndExtra DWORD?
hInstance DWORD?
hIcon DWORD?
hCursor DWORD?
hbrBackground DWORD?
lpszMenuName DWORD?
lpszClassName DWORD?
hIconSm DWORD?
WNDCLASSEX ENDS

  • cbSize: WNDCLASSEX size. We can use sizeof (WNDCLASSEX) to obtain an accurate value.
  • style: window class derived from this window with style. You can use "or" operator to put together a few styles or.
  • lpfnWndProc: window handler pointer.
  • cbClsExtra: designated immediately after the window class structure of the additional number of bytes.
  • cbWndExtra: examples specified in the window immediately after the additional number of bytes. If an application in terms of resources used pseudo-CLASS command to register a dialog class, you must set this member DLGWINDOWEXTRA.
  • hInstance: This module handles the case.
  • hIcon: Handle of the icon.
  • hCursor: cursor handle.
  • hbrBackground: the background of the painting brush handle.
  • lpszMenuName: the pointer point to the menu.
  • lpszClassName: type the name of the target point.
  • hIconSm: window class and the associated small icon. If the value is NULL. HCursor put into the icon of the small size of the appropriate icon.

invoke CreateWindowEx, NULL, \
ADDR ClassName, \
ADDR AppName, \
WS_OVERLAPPEDWINDOW, \
CW_USEDEFAULT, \
CW_USEDEFAULT, \
CW_USEDEFAULT, \
CW_USEDEFAULT, \
NULL, \
NULL, \
hInst, \
NULL

Register window class, we will call CreateWindowEx to create the actual window. Please note that the function of 12 parameters.

CreateWindowExA proto dwExStyle: DWORD, \
lpClassName: DWORD, \
lpWindowName: DWORD, \
dwStyle: DWORD, \
X: DWORD, \
Y: DWORD, \
nWidth: DWORD, \
nHeight: DWORD, \
hWndParent: DWORD, \
hMenu: DWORD, \
hInstance: DWORD, \
lpParam: DWORD

Let's take a closer look at these parameters:

  • dwExStyle: Additional window styles. Compared to the old CreateWindow This is a new parameter. In 9X/NT you can use the new window style. Style You can specify the general style of the window, but some special window styles, such as top-level window must be specified in this parameter. If you do not want to specify any particular style, while this parameter is set to NULL.
  • lpClassName: (required). ASCIIZ form of the address window class name. Can be your custom category, it could be a predefined class name. As mentioned above, each application must have a window class.
  • lpWindowName: ASCIIZ form of the name of the address window. The name will appear in the title of the article. If the parameter blank, then the title of the article have nothing.
  • dwStyle: window style. In this window you can specify the appearance. This parameter can specify zero, but not as the window system menu, there is no maximize and minimize buttons, there is no Close button, as you have to press Alt + F4 to close it. The most common type of window style is WS_OVERLAPPEDWINDOW. A window style is a bit mask based on, so that you can use "or" the window you want to style or up. WS_OVERLAPPEDWINDOW as by several of the most inconvenience to the general style or up.
  • X, Y: the upper left corner of the window specified in pixels of the screen coordinates of the location. Can be designated as a default to CW_USEDEFAULT, so Windows will automatically designate the most suitable for the window position.
  • nWidth, nHeight: in pixels of the window size. Can be designated as a default to CW_USEDEFAULT, so Windows will automatically designated as the most suitable window size.
  • hWndParent: parent window handle (if any). This parameter tells Windows which is a sub-window and the window of his father is. This MDI (Multiple Document structure) is different from the child window here is not confined to the parent window's client area. He only used to tell Windows all the father and son relationship between the window to the parent window is destroyed with the destruction of its sub-window. In our example program because there is only one window, so the parameter is set to NULL.
  • hMenu: WINDOWS menu handle. If only the system parameters menu is designated for the NULL. Looking back lpszMenuName structure WNDCLASSEX parameters, it also specify a menu, this is a default menu for any window class derived from the window menu if required by other parameters in the re-designation. In fact, the parameters of a double meaning: on the one hand, if this is a custom window menu handle on behalf of the parameter, on the other hand, if this is a pre-defined window, the parameters of the window on behalf of the ID. Windows is based on the distinction between lpClassName parameters window is custom or pre-defined window.
  • hInstance: have the application window instance handle.
  • lpParam: (optional) To point to the window structure of the pointer data type parameters. If the MDI window in the resulting structural parameters CLIENTCREATESTRUCT delivery. Under normal circumstances, the total value of zero, which means that there is no parameter passed to the window. GetWindowLong function can retrieve the value.

mov hwnd, eax
invoke ShowWindow, hwnd, CmdShow
invoke UpdateWindow, hwnd

After the success of CreateWindowEx call, in window handle in eax. We must preserve the value for later use. We have just created will not automatically display window, it is necessary to call to ShowWindow in accordance with the way we hope to show the window. The next call to update the client area UpdateWindow.

. WHILE TRUE
invoke GetMessage, ADDR msg, NULL, 0,0
. BREAK. IF (! Eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
. ENDW

At this time we have shown in the window on the screen. But it can not receive messages from the outside world. Therefore, we must give the relevant information it provides. We are through a news cycle to complete the work. Each module has only one news cycle, we continue to call GetMessage get information from Windows. GetMessage send a MSG structure to Windows, then Windows in the function to fill the relevant information has been filled with the Windows find and post the good news GetMessage will return. During this time the system control may be transferred to other applications. This constitutes a multi-task under Win16 structure. If GetMessage received news WM_QUIT will return FALSE, so that the end of the cycle and exit the application. TranslateMessage is a utility function is a function, which has the original keys from the keyboard to receive information, and then interpreted as WM_CHAR, in the Add WM_CHAR message queues, because after the explanation of the key messages contained in the ASCII code, which the scan code than the original good understanding much more. If your application does not deal with key messages, you can not call the function. DispatchMessage will send a message to the process responsible for the window function.

mov eax, msg.wParam
ret
WinMain endp

If the end of the news cycle, from the code stored in the wParam of MSG, you can put it in the register eax to the Windows did not take advantage of the current Windows code to the end, but we better have to comply with anti-accident Windows norms.

WndProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM

It is our window handler. You can not name to the function. The first parameter is the hWnd of the window to receive messages handle. uMsg is the message received. Note uMsg is not a MSG structure, in fact, on only a few type DWORD. Windows define hundreds of messages, the majority of your application will not deal with. When the news of the window at the time, Windows will send a message related to the window. The process of its window function will be to deal with these sources of intelligence. wParam and lParam only additional parameters to facilitate the transmission of more information and the relevant data.

. IF uMsg == WM_DESTROY
invoke PostQuitMessage, NULL
. ELSE
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
. ENDIF
xor eax, eax
ret
WndProc endp

Above can be said to be a key part. This is why we need to write Windows programs to rewrite the main part. Process here to check your messages from Windows pass, if we are interested in news to be addressed, dealt with, in the eax register in the transmission of 0, he must call DefWindowProc, the process of the window to receive the parameters passed to the lack of Province to deal with the window function. All the news you need to be addressed is WM_DESTROY, when your application to the end of Windows Messaging in, when your application to explain to the message on the screen it has disappeared, this is only notice of your application window has been destroyed, you have to prepare to return to Windows. In this message you can do some clean-up work, but can not stop out of the application. If you want to do that, you can handle WM_CLOSE message. End clean-up in dealing with work, you must call PostQuitMessage, the function will return a message WM_QUIT your application, and which will make GetMessage return, and put in the eax register 0, and then the end of the news cycle and return WINDOWS . You can process your call DestroyWindow function, it will send a WM_DESTROY message to your own applications, so as to force it to withdraw from.



Assembly Language Tutorial Articles


Can't Find What You're Looking For?


Rating: Not yet rated

Comments

No comments posted.