.1. Introduction to the environment and foundation of Win32
In the DOS, we can manage all resources of the system, we can change all the memory in the system, such as the memory control block to allocate memory, modify the interrupt vector table to intercept the interrupt, etc., the other operations, If we directly operate the keyboard port directly, you can describe the DOS system: The system has only one privilege level. In programming, any program and operating system are in the same level, so under DOS, one editor The bad program will affect all other programs. If a program turns off the keyboard port, all programs cannot be typed from the keyboard until any program reopen the keyboard, one program falls into a dead cycle. No other programs can terminate it. The programming idea under DOS is "single task", as you think your program will follow your process step by step, you don't have to consider the problem (of course the program may be interrupted, but you can think they will put Environment recovery, if the interrupt program does not recover the environment, it is their fault). In memory management, DOS assembly and Win32 assembly have many different: DOS work In real mode, we can address 1M memory, addressing the initial address of the segment when the segment register is addressed, each segment size is 64K, more than 1M part, only use him as XMS, that is, it can only be used as data storage and cannot execute it. And Windows executes in protection mode, all resources are "protected" for applications: Programs have levels in execution, only operating system works in the highest level --0, all applications All working in Level 3 (Ring3), in Ring3, you can't access the IO port directly, you can't access the memory running in other programs, and even write data to the program own code segment is illegal, will be on the Windows screen Extended a familiar blue screen. Only a program for Ring0 is fully open. In terms of memory, Windows uses the processor's paging mechanism so that all memory is "flat", you don't have to use a segment register to specify the address of the segment, because in the protection mode, segment register The meaning is different (see books in 80386 manual), you can specify a 32-bit address to address 4GB of memory. In terms of program structure, the Windows program is also very different. It is "message", you can imagine such a common windows window, there are several buttons above, if you use DOS programming ideas, you will find It is difficult to implement it: When the mouse moves to the edge of the window, dragging the window size. When you click the button, you will do something to do, you will find that your program is waiting since the start of execution, you don't know the mouse first What is the place, in fact, you are waiting for all possible things. And under DOS, you can just implement it first, when you need to enter, stop, you don't enter, don't execute, and I let you enter data A You can't enter data B. Ok, the words come true, because the above is the foundation of Win32 programming, whether it is also the same for Win32 compilation or VC , they are all the same, let's take a look at the content about Win32 compilation.
2.Win32ASM compiler
There are two most commonly used by Win32ASM: Borland's Tasm5.0 and Microsoft's Masm6.11 or higher, both compilers have their own advantages and disadvantages, TASM has a unclear IMPORT library, and Masm has no belt, but MASM is optimized above the code, but it is better than TASM, but it does not take the Import library. It seems that it is more difficult to choose, but Steve Hutchesson gave us an answer. He established a full Import library for MASM, basically involving most of the API functions of Windows, these libraries, The include files and other tools have Masm6.14 versions together into a Masm32 compiler - Masm32v5. In this way, we use the assembly programming as easy as C. Because of Masm32V5, I personally, I recommend using MASM as a compilation tool for Win32ASM, but MASM and TASM's macro syntax have many different, my tutorial is written in MASM format. 3. Masm32 environment setting
In Win32 programming, because Windows has a lot of data structures and definitions, these are placed in the include file, and it is also used to use the import library (the popular talk is the list of functions in the DLL file provided by Windows, that is, tell Where is the program to call an API function), these are placed in the include and lib directory. We should specify the following system environment when compiling:
Set include = / masm32v5 / includeset lib = / masmv5 / libset path = / masmv5 / bin
This way the compiler will go to the correct path to find the include file and lib file. You can add the above statement in the autoexec.bat file, in order to generate the execution file in the Windows PE format, you want to specify the corresponding parameters in compilation and connections:
Compile: ML / C / COFF file name .asm connection: link / subsystem: windows obj file name. Obj resource file name .res
In order not to hit so many parameters every time you compile, we can use the nmake file to be executed for execution. NMAKE is the code maintenance program, he will check. Sasm .obj .exe .res and other files, if you update the source Procedure, he will automatically perform a compiler or a connection program to generate a corresponding file. You can specify the compiler and connector and the corresponding parameters in the file name Makefile, and the following is an example of a Makefile file:
Name = clockobjs = $ (name) .Objres = $ (name) .res $ (name) .exe: $ (objs) $ (rs) LINK / Debug / Subsystem: Windows $ (OBJS) $ (RES) $ ( : $ (Name) .RC RC $ (Name) .rc .asm.obj: ml / c / coff $ (name) .asm
The file tells the NMAKE program, the program is named clock, generating the clock.exe file requires a clock.obj and clock.res file, and the clock.rs file is required to use the clock.obj file to use the clock.asm file, As for whether ML, LINK, and RCs need to be executed, the program automatically determines according to the time of the file.
2. Structure and syntax of Win32ASM programs
Let's take a look at a simplest Win32 assembler:
.386
.Model flat, stdcall
Option Casemap: None; Case Sensitive
INCLUDE Windows.inc
INCLUDE KERNEL32.INC
IncludeLib kernel32.lib
.DATA
SZCAPTION DB 'WIN32 Assembly Examples', 0
Sztext DB 'Win32 Compilation, Simple and Powerful!', 0
.code
Start:
Invoke Messagebox, Null, Addr Sztext, Addr Szcaption, MB_OK
Invoke EXITPROCESS, NULL
End Start
This is the simplest Win32 assembler that can be implemented. I will simply introduce the role of each part:
.386
The same is true for this statement and DOS, which is to tell the compiler that we need to use the 80386 instruction set, because 32-bit assemblers use 32-bit registers such as EAX, EBX, etc., this sentence is must, of course You can also use .486, .586, etc., use .386p, .486p, etc.
.Model flat, stdcall
.MODEL tells the compiler program mode, people who have edited DOS assembly may know that there is Tiny, Small, ... huge, etc. in the DOS program, which specifies the program memory logo, in huge and other modes, memory find Site and subroutine calls will use FAR format, but in Win32 assembly, you can only use a mode, FLAT mode, because the Win32 program is used, memory is a continuous 4GB segment, does not matter small or large mode. The stdcall tells the transfer method of the compiler parameter. When the subroutine is called, the parameters are three types passing through the stack. Stdcall, C and PASCAL, and STDCALL specifies the parameters from right to left into the stack, For example, for a Windows API such as MessageBox, this is defined in the manual:
Int messagebox
HWND HWND, // Handle of Owner Window
LPCTSTR LPTEXT, / / Address of Text In Message Box
LPCTSTSTR LPCAPTION, / / Address of Title of Message Box
Uint utype // style of message box
);
So we can call it like this in assembly:
Push utype
Push LPCAPTION
Push lptext
Push hwnd
Call MessageBox
Everyone should pay attention to the rightmost parameters is the last pile of stack. Of course, we don't have to call an API like this, because a macro statement in Masm not only helps us complete all the stack operations, and help us check the parameters Whether the number is correct, that is, the Invoke statement, we can change the above statement into invoke messagebox, hwnd, lptext, lpcaption, utype. If the actual parameters in this program become Invoke Messagebox, NULL, AddR Sztext, AddR Szcaption, MB_OK.
INCLUDE statement
The include statement contains some system definitions and API letters, where all Windows data structures definitions and constant definitions are included in Windows.inc, and other API functions are included in xxx.inc, such as check Microsoft Win32 Programmer's Reference knows EXITPROCESS is included in kernel32.dll, then we will include include the include Kernel32.inc and includeLIDELIB KERNEL32.LIB statement in the program, otherwise an error that does not define an API function when compiling. MessageBox is in user32.dll, then we have to include include the include user32.inc and includeelib user32.lib statement .DATA or .DATA ?DATA or .DATA?
The next is the data segment ,.data defines a predefined variable ,.data? Defines the unmelted variable, the difference between the two is .DATA? The variable defined is not occupied .EXE file size, and It is dynamically allocated when the program is executed, so the data that does not specify the initial value can be placed in the .DATA section, such as a 1K size buffer, put it in .Data?, The program will not add one byte.
.code
Indicates that the next is the code segment, all of our code is placed here. The last START statement specifies the statement that the program starts executing. EXITPROCESS in the program is a standard WIN32 API, corresponding to INT 20H or MOV AH, 4CH / INT 21H in DOS assembly, that is, the program exits. Messagebox is also a standard API. The function is to display a message box on the screen. The specific parameters have explained that there is also note that invoke messagebox, null, addr sztext, addr szcaption, MB_OK statement, MB_OK and NULL It has predefined in Windows.inc.
3. A simple dialog --- Significant resource files using resource files
Regardless of programming under DOS or programming under Windows, we always use many other data, such as sound data, graphics data, text, etc., in DOS, we can define these files under DOS. Format, but in this way, there has been a lot of resources sharing. You may still remember a lot of games under DOS, and their graphics are stored in their format, you can't use standard view software. It is not possible to save it as other formats. Although we can still do this in Win32, but Win32 is programmed to us a solution - it is a resource file that is unified, including strings, graphics, dialogs, and the above buttons, text, etc. In the file, it can be convenient to use it in different files. Most importantly, if we use your own file format, you should involve reading and writing operations in these files, but complicated, but use the resource file, Windows offers a range of APIs to load resources. Very convenient. Now let's take a very simple source file for the source file, its extension is .rc, when it is compiled with the resource compiler, you can enter the .exe file when you use the .RES file.
#include
#define DLG_MAIN 1
DLG_MAIN DIALOGEX 0, 0, 236, 185
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENUCAPTION "Dialog Template"
Font 9, "Song"
Begin
Defpushbutton "Exit", IDOK, 177, 163, 50, 14
Control "", -1, "static", ss_etchedhorz, 7,155,222,1
End
Now I briefly explain the syntax of the.rc file:
#include
#define DLG_MAIN 1 - Similar to the EQU statement of the .asm file, the same as the assembly source, these definitions are for program readability.
DLG_MAIN DIALOGEX 0,0,236,185
Windows .rc files can define Bitmap, Cursor, Icon (Icon), Accelerators, Dialog, Menu, StringTable, RCDATA (self 8 kinds of resources such as defining resources, detailed description, can refer to books about MFC, in the syntax of the resource compiler in Win32ASM, the general format is the definition method of these resources:
Bitmap definitions: nameID BITMAP filename cursor defined [load-mem]: nameID CURSOR filename icon definitions [load-mem]: nameID ICON [load-mem] filename accelerator key definitions: acctablename ACCELERATORS [optional-statements] BEGIN event, idvalue, [Type] [options]. .ndions.
Wait, specific definitions and parameters can refer to the RC.HLP help file in Masm32v5. (You can download it in the programming tool), we can use the resource editor to edit resources, or you can define your resources yourself in your text editor yourself.
Use resources in the program
In the program, you must first install such a memory before using the resource. Windows defines a range of APIs to load resources, such as LoadMenu, LoadString, LoadBitmap, etc. Application Instance LPCTSTR LPBITMAPNAME / / Address of Bitmap Resource Name); These Load functions return values are a handle, which is generally at least two items in the call: Hinstance and Resoucename, this resouncename (such as bitmapname, mename) is in the resource file #define specified value, if you define an icon with #define my_ICON 10 / my_icon icon "main.ico", you can use Loadicon (Hinstance, 10) in the program to be loaded with LoadCon (Hinstance, 10) Icon file 10. Another parameter hinstance is the handle of the execution file, which corresponds to the file name where the resource is located, you can get Hinstance with Invoke getModuleHandle, NULL when executing the program. Other resources are not explicitly mounted, such as dialog resources, which is loaded by Windows in the functions of the dialog, in the following example Invoke DialogBoxParam, Hinstance, DLG_Main, Null, Offset _PrOcdlgmain, 0 is a dialog that has been defined in a resource file on the screen, and there is no API such as loadDialogbox to first load the dialog. Win32ASM - Display a dialog
Introduced so many related things, let us see how to display a dialog, the source program is as follows:
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
PROGRAMMED by Luo Yunbin, Bigluo@telekbird.com.cn
; Website: http://asm.yeah.net
Luoyunbin's Win32 ASM Page (Luo Yunbin's Programming Park)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.386
.Model flat, stdcall
Option Casemap: None; Case Sensitive
INCLUDE Windows.inc
INCLUDE USER32.INCINCINCLUDE KERNEL32.INC
INCLUDE COMCTL32.INC
INCLUDE COMDLG32.INC
INCLUDELIB USER32.LIB
IncludeLib kernel32.lib
INCLUDELIB COMCTL32.LIB
INCLUDELIB COMDLG32.LIB
DLG_MAIN EQU 1
.DATA?
Hinstance DD?
SZBuffer DB 256 DUP (?)
_PrOCDLGMain Proto: DWORD,: DWORD,: DWORD,: DWORD
.DATA
.code
*********************************************************** *******************
_PrOcdlgmain Proc Uses EBX EDI ESI, /
HWND: DWORD, WMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD
MOV EAX, WMSG
.IF EAX == WM_Close
Invoke EndDialog, Hwnd, Null
.ELSEIF EAX == WM_INITDIALOG
.ELSEIF EAX == WM_COMMAND
Mov Eax, WPARAM
.IF EAX == IDOK
Invoke EndDialog, Hwnd, Null
.ELSEIF EAX == Idcancel
Invoke EndDialog, Hwnd, Null
.endif
.lse
Mov Eax, False
RET
.endif
Mov Eax, True
RET
_PrOCDLGMain ENDP
*********************************************************** *******************
Start:
Invoke INITCOMMONCONTROLS
Invoke getModuleHandle, NULL
Mov Hinstance, EAX
Invoke Dialogboxparam, Hinstance, DLG_MAIN, NULL, OFFSET _PROCDLGMAIN, 0
Invoke EXITPROCESS, NULL
End Start
After reading a few articles, most of this statement should be very familiar, I will explain a few new statements:
_PrOCDLGMain Proto: DWORD,: DWORD,: DWORD,: DWORD
The PROTO statement is similar to the function definition in the C language. In Win32 assembly, if the subroutine is defined after reference, you must first define, of course, this definition is called for invoke statements and other parameters, if you The subroutine does not have a parameter, you can use the CALL instruction to call it instead of using the macro invoke, you don't have to declare this function.
_PrOCDLGMain Proc Uses EBX EDI ESI, / HWND: DWORD, WMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD
This definition of Proc statement should be unfamiliar. To repeat the Uses and the following parameters, the registers under Usees indicate that the compiler is automatically inserted into the instructions of these registers, / is in Masm32. Symbols, indicating that the next line is the continued content of the Bank to avoid excessive content in a row. The following hWnd: DWORD statement defines the parameters that call this subroutine, if you have the following definition MyProc Proc DWPARA1: DWORD, DWPARA2: DWORD, DWPARA3: DWORD, then you call it with Invoke MyProc 1, 2, 3, then, 1, 2, 3 will be assigned to DWPARA1, DWPARA2, DWPARA3, respectively, and you can use these passing parameters in the subroutine. If the type of parameters is double word, then DWORD can be omitted. .if / .else / .elseif / .ndif
These statements are macro, but do not say that you also know what they mean, with these macro, we can clarify the assembly as C, but not always see JMP instructions, of course, this only However, the compiler will help you do these things. If you go to the reverse assembly, you will start to see a lot of JMP instructions, .IF's format is as follows .IF EAX == 1 If EAX is equal to 1.IF Eax! = 1 If EAX is not equal to 1.IF EAX! = 1 && EBX! = 2 If EAX is not equal to 1 and EBX is not equal to 2.IF EAX == 1 || EBX == 2 If EAX is equal to 1 or EBX equal to 2 other macro There is also .While / .ndw .break, etc., you can refer to Masm32v5 help file Masm32.hlp
Finally, what is the DialogBoxParam this API. In Windows, all the windows must specify a subroutine, when Windows detects the mouse, timer, etc., it is called, which is called with this subroutine. It is the most basic concept of Windows based on the message-based system. In other words, under DOS, we call the system through the int instruction, and under Windows, there are many time you specify the subroutine address to make Windows to call you. INVOKE DIALOGBOXPARAM, HINSTANCE, DLG_MAIN, NULL, OFFSET _PROCDLGMAIN, 0 _ s _ _ 指 消 消 子 子 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序 程序Hinstance is the handle of the resource file where the dialog is located. In addition, in the _proCDLGMain subroutine, Windows passed to our 4 parameters hWnd, WMSG, WPARAM, LPARAM, where hWnd is the window handle of the dialog, WMSG indicates the current message event, such as this dialog, Windows will Calling with WM_INITDIALOG, WM_CLOSE is WM_CLOSE, when the button on the dialog is turned off, WM_COMMAND, WM_COMMAND, etc. 4. Write a simple window
Basic knowledge about the window
The window is the rectangular area on the screen. One window can accept the user's input from the keyboard or mouse and display the graphic output inside. An application window typically contains the program's title bar, menu, border, and scroll bar. Among them, the dialog is also a window. Different, the dialog surface typically contains several other windows called "sub-windows". The form of these sub-windings has a press button, a radio button, a checkbox, a text input area, a list box, and a scroll bar. Users see these windows as an object on the screen, can directly interact directly with these objects by pressing a button or scrolling a scroll bar. The window receives the input of the window in the "message", and the window also uses messages to communicate with other window. For example, when changing the size of the program window, the word processor will reformat the text. The details of the window size change are processed by the operating system, but the program can respond to this system function. When the user changes the size of the window, Windows sends a message to the program indicates the size of the new window. Then, the program can adjust the content in the window to respond to changes in the size. Each window created by the program has a related window process. That is to specify a subroutine (window process) to this window, Windows sends a message to the window by calling it. The window process is processed according to this message and then returns the control to Windows. The window is created on the basis of "Window". Windows defines the provincial window procedure. If you make Windows yourself in your own, then you can get a standard window, you can also choose the news that you are interested in, this is equivalent to production. Different subclasses also form different applications. Similarly, the sub-window is also based on the same window class and uses the same window process. For example, all buttons in all Windows programs are based on the same window class. This window class has a window process that handles all button messages, but if you design a button according to your own ideas, if you want to change the surface of the button into a bitmap, you can handle the WM_PAINT message of the button window, when Windows needs When you draw button surface, you can paint it with your own meaning. After the Windows program starts execution, Windows creates a "message queue" for the program. This message queue is used to store messages of various windows that the program may create. There is a code in the program called "message loop", which is used to remove messages from the queue and send them to the corresponding window process. When there is no message, your program is actually transferred in the message loop. The process of creating a window is as follows: Get an instance handle of the program (Hinstance) Registration window class, actually to specify the process of processing the message for your window, define the cursor, window style, color and other parameters Create a window display window and enter the message loop. That is, there is no message, and send it to the window process.
Creating a window in different programs is actually almost exactly the same, so you can copy this paragraph when you compose a new program, slightly modify it, most of the code is actually used in the window. In the process, because this is the difference in different programs. The programming points of the window process are as follows:
The parameter UMSG transmitted from the Windows to the window process gets the message type and goes to a different branch processed. To return to Windows, you must return 0 in EAX when returning to Windows. I don't have the message that I don't deal with, I must call the DEFWINDOWPROC process and turn the return value back to Windows. Otherwise, Windows will not be displayed.
There are more than 280 messages specified in the UMSG parameter. In fact, there are several more important to handle, such as Windows send WM_CREATE messages when they are created, we can initialize, allocate memory, etc., while exiting WM_CLOSE will be sent, we can release the memory, etc. Clear operation, when the menu or button on Windows is pressed, the WIN32 Programmer's Reference can be referred to Win32 Programmer's Reference. Below, let's take a look at a simple program that creates a window. A program for creating a window
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
PROGRAMMED by Luo Yunbin, Bigluo@telekbird.com.cn
; Website: http://asm.yeah.net
Luoyunbin's Win32 ASM Page (Luo Yunbin's Programming Park)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.386
.Model flat, stdcall
Option Casemap: None; Case Sensitive
INCLUDE Windows.inc
INCLUDE User32.inc
INCLUDE KERNEL32.INC
INCLUDE COMCTL32.INC
INCLUDE COMDLG32.INC
INCLUDE GDI32.INC
INCLUDELIB USER32.LIB
IncludeLib kernel32.lib
INCLUDELIB COMCTL32.LIB
INCLUDELIB COMDLG32.LIB
IncludeLib GDI32.LIB
IDI_MAIN EQU 1000; icon
IDM_MAIN EQU 4000; Menu
IDM_EXIT EQU 4001
.DATA?
Hinstance DD?
HwinMain DD?
HMENU DD?
SZBuffer DB 256 DUP (?)
.DATA
SzclassName DB "Windows Template", 0
SZCAPTIONMAIN DB 'window template', 0
.code
Start:
Call_winmain
Invoke EXITPROCESS, NULL
_WinMain Proc
Local @stwcmain: WNDCLASSEX
Local @stmsg: msg
Invoke INITCOMMONCONTROLS
Invoke getModuleHandle, NULL
Mov Hinstance, EAX
Invoke Loadicon, Hinstance, IDI_MAINMOV HICON, EAX
Invoke loadmenu, hinstance, idm_main
Mov Hmenu, EAX
************** Register window **************************************** **********
Invoke loadCursor, 0, IDC_ARROW
Mov @ stwcmain.hcursor, EAX
Mov @ stwcmain.cbsize, sizeof wndclassex
Mov @ stwcmain.hiconsm, 0
Mov @ stwcmain.style, cs_hredraw or cs_vredraw
Mov @ stwcmain.lpfnwndproc, Offset WNDMAINPROC
Mov @ stwcmain.cbclsextra, 0
Mov @ stwcmain.cbwndextra, 0
Mov Eax, Hinstance
Mov @ stwcmain.hinstance, EAX
Mov @ stwcmain.hicon, 0
Mov @ stwcmain.hbrbackground, color_window 1
Mov @ stwcmain.lpszclassname, offset szclassname
Mov @ stwcmain.lpszMenuname, 0
Invoke registerclassex, addr @stwcmain
; ************** Establish an output window ****************************************** *********
Invoke CreateWindowex, WS_EX_CLIENTEDGE, /
Offset szclassname, Offset Szcaptionmain, /
WS_OVERLAPPEDWINDOW OR WS_VSCROLL or WS_HSCROLL, /
0, 0, 550, 300, /
NULL, HMENU, HINSTANCE, NULL
Invoke ShowWindow, Hwinmain, SW_SHOWNORMAL
Invoke UpdateWindow, HwinMain
************** Message loop ***************************************** ***********
.While true
Invoke GetMsg, NULL, 0, 0
.break .if eax == 0
Invoke TranslateMsg, Addr @stmsg
Invoke DispatchMessage, Addr @STMSG
.endw
RET
_WinMain ENDP
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
WNDMAINPROC PROC Uses EBX EDI ESI, /
HWnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD
MOV EAX, UMSG
.IF EAX == WM_CREATE
Mov Eax, HWnd
Mov Hwinmain, EAX
Call _init; ********************************************************************************************************************************************************************************************************************************************************************************************** ********************
.ELSEIF EAX == WM_COMMAND
.IF lparam == 0
Mov Eax, WPARAM
.IF AX == idm_exit
Call_quit
.endif
.endif
*********************************************************** *******************
.ELSEIF EAX == WM_Close
Call_quit
*********************************************************** *******************
.lse
Invoke DefWindowProc, Hwnd, UMSG, WPARAM, LPARAM
RET
.endif
XOR EAX, EAX
RET
WNDMAINPROC ENDP
_Init proc
Invoke SendMessage, HwinMain, WM_SETITION, ICON_SMALL, HICON
RET
_Init ENDP
*********************************************************** *******************
_Quit Proc
Invoke DestroyWindow, HwinMain
Invoke PostquitMessage, NULL
RET
_Quit ENDP
*********************************************************** *******************
End Start
Analysis of window programs
Let's simply analyze this program, first programs _winmain, define two local variables @stmsg and @stwinmain in _winmain, data types are MSG and WNDCLASSEX structures. In the reference manual, you can see WNDCLASSEX definitions. All parameters of a window, such as the menu, cursor, color, window procedure, etc. .lpfnwndproc, Offset WNDMAINPROC defines the window process of processing messages, Mov @ stwcmain.lpszclassname, offset szclassname defines the name of the class you want to create, then use RegisterClassex to register this window class, note that the window is not created, you Just define a subclass, let go to create a window with the class you define. That is, use the CreateWindowEx function to create it. In the manual, CreateWindowex is defined in this:
HWND CreateWindowEx (DWORD dwExStyle, // extended window style LPCTSTR lpClassName, // pointer to registered class name LPCTSTR lpWindowName, // pointer to window name DWORD dwStyle, // window style int x, // horizontal position of window int y, / / vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window hMENU hMenu, // handle to menu, or child-window identifier hINSTANCE hInstance, // handle To Application Instance LPVOID LPPAAM / / POINTER TO WINDOW-CREAM / / POINTER TO WINDOW-CREATION DATA); where DWEXStyle is the style of the window, LPClassName is the name of our own defined class. If you want to create a defined class, such as a RicheDit class, etc., just put lpClassName points to the "RicheDit32" string, of course, you don't have to use registerclass and write your own window procedure. After executing CREATEWINDOWEX, get a return value is the window handle, this value is often used frequently, so save it first. At this time, the window is not displayed on the screen, but is in a hidden state, we have to use ShowWindow to display the window and draw the contents of the window with UpdateWindow. After the window is displayed, the program enters a loop ---- message loop, I have said before, the role is to keep the Windows message and send it to the window process. GetMessage removes a message from the message queue. If the result is not wm_quit, then getMessage returns a non-zero value, otherwise returns zero, at this time, the program executes the EXITPROCESS to return the operating system. TranslateMessage converts the message to handle some shortcuts, and DispatchMessage sends the process-processed message back to Windows, processes the Windows call window process. When the window process is complete, the program returns from DispatchMessage, thus starting A getMessage call. The parameters of these letters can refer to the manual.
Analysis of the window process
The window process has four parameters, hWnd is the handle of this window, the same value, the value returned when the window is created, the UMSG is the type of message, WPARAM, and LPARAM are the parameters of the message, the meaning and value of the message are different depending on the message. . In this program, we deal with WM_CREATE, WM_COMMAND, and WM_QUIT messages, then return 0, for non-processed messages, use Invoke DefWindowProc, HWND, UMSG, WPARAM, LPARAM, and use RET to transfer the return value back to Windows. When responding to a WM_CLOSE message, we use the DestroyWindow to clear the window and generate a WM_QUIT message with PostQuitMessage so that the program returns 0 when the message loop calls GetMessage to end the message loop and end the program. 5. Use the menu and acceleration keys to use the menu and accelerator
The menu is the most important component of the Windows standard interface. The menu bar of the window is below the title bar. This menu is often referred to as the main menu, and the menu item listed in the main menu is called a drop-down menu, or pop-up menu , Submenu, etc., and click on the icon on the left side of the title bar to pop up a menu, called the system menu. The accelerator is actually a shortcut key of the menu item, and the application often marks the shortcuts of the menu item on the right side of the menu item, which is the accelerator button. The structure of the menu is nested, that is, you can pop up another menu when you select a menu item. The type of menu item is normal, disabled, ash, horizontal separation line, etc. This section demonstrates various types of menus: You can see normal and disabled, gray menu in the main menu, you can use the right-click window to pop up a "pop-up menu", too I can see that I have added a few new content in the system menu. In programming processing, the menu is defined in the resource file (of course, you can use the resource file, and use the AppendMenu one item in the program, but use the resource file is undoubtedly the easiest way), then Use loadMenu to get the menu handle to use. The syntax defined in the resource file is as follows:
Menu ID Menu Discardable
Begin
Popup "Main menu item"
Begin
MenuItem "pop-up menu item", command ID [, option]
MenuItem "pop-up menu item 2", command ID [, option]
Menuitem Separator
MenuItem "pop-up menu item three", command ID [Option]
...
End
Popup "Main menu item 2"
Begin
MenuItem "pop-up menu item", command ID [, option]
MenuItem "pop-up menu item 2", command ID [, option]
MenuItem "pop-up menu item three", command ID [Option]
...
Popup "Nested Menu Item"
Begin
MenuItem "pop-up menu item", command ID [, option]
MenuItem "pop-up menu item 2", command ID [, option]
MenuItem "pop-up menu item three", command ID [Option]
...
End
End
...
End
Menu ID is the resource number we use to load menu in the program. The MenuItem Separator defines the horizontal line with the separated menu item. The option in the menu item definition is attribute, such as grayed is ashing, INACTIVE is disabled and many more. The accelerator is actually defined the hotkey corresponding to each menu item, the definition method is as follows: Accelerator key ID Accelerators
Begin
VK_F1, corresponding menu command ID, Virtkey
VK_F2, corresponding menu command ID, Virtkey
...
"A", corresponding menu command ID, Virtkey, Control
"B", corresponding menu command ID, Virtkey, Control
End
Among them, the accelerator key ID is the resource number we loaded in the program with loadAccelerator. Each of the following is defined, and VK_F1 represents the f1, "a" to indicate the key A, the following Virtkey is required, and then The following Control "or Shift, Alt" means using the Control key combination, that is, if you define: "c", idm_copy, virtkey, control and define menuItem "copy" in the menu definition, IDM_copy, then you Pressing Ctrl-C in the program to actually execute the menu item "copy". The programming of the menu and accelerator is very simple, and some of the initialization you need to do the following:
The instance of the program is loaded with the loadMenu to load the menu. Get the menu handle to load the acceleration key with the loadaccelerator. Get the Accelerator Handle Registration window class Create a window to create a menu handle display window and enter the message loop, in the message loop Use TranslateAccelerator to detect acceleration keys (see the source program)
When the window is displayed, when a menu item or an accelerator button is pressed, Windows sends a WM_COMMAND message to the window process, and when the menu item in a system menu is pressed, Windows sends a WM_SYSCOMMAND, menu item command to the window process. The ID is included in the low 16 bits of WPARAM, in the general programming, if we don't process the system menu message, then just create a paragraph in the process of the WM_COMMAND message. IF / .elseif / .elseif ... / .endif's statement is handled for each menu command ID.
Source programs using menus and acceleration keys
.386
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
PROGRAMMED by Luo Yunbin, Bigluo@telekbird.com.cn
; Website: http://asm.yeah.net
Luoyunbin's Win32 ASM Page (Luo Yunbin's Programming Park)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Folder
Option Casemap: None; Case Sensitive
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Include data
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
INCLUDE Windows.inc
INCLUDE User32.inc
INCLUDE KERNEL32.INC
INCLUDE COMCTL32.INC
INCLUDE COMDLG32.INC
Include shell32.inc
INCLUDE GDI32.INC
INCLUDELIB USER32.LIB
IncludeLib kernel32.lib
INCLUDELIB COMCTL32.LIB
INCLUDELIB COMDLG32.LIB
IncludeLib shell32.lib
IncludeLib GDI32.LIB
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
; EQU data
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Idi_main EQU 1000; icon
IDA_MAIN EQU 2000; Accelerator
IDM_MAIN EQU 4000
IDM_Open EQU 4101
IDM_OPTION EQU 4102
IDM_EXIT EQU 4103
IDM_SETFONT EQU 4201
IDM_SETCOLOR EQU 4202
IDM_FIND EQU 4203
IDM_FINDPREV EQU 4204
IDM_FINDNEXT EQU 4205
IDM_TOOLBAR EQU 4206
IDM_Toolbartext EQU 4207
IDM_INPUTBAR EQU 4208
IDM_STATUSBAR EQU 4209
IDM_HELP EQU 4301
IDM_ABOUT EQU 4302
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Data segment
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.DATA?
Hicon DD?
Hinstance DD?
HwinMain DD?
HMENU DD?
HSUBMENU DD?
SZBuffer DB 256 DUP (?)
DWFLAG DD?
*********************************************************** *******************
Sign Definition
F_toolbar EQU 00000001B
F_toolbartext EQU 00000010B
F_INPUTBAR EQU 00000100B
F_statusbar EQU 00001000B
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> Data segments
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.DATA
SzclassName DB "Menu Example", 0
SZCAPTIONMAIN DB 'Menu Application Example', 0
SzMenuhelp DB "Help Theme (& H)", 0
Sz GeneNuabout DB "About this Program (& A) ...", 0
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Code segment
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.code
INCLUDE Debug.asm
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Procedure
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> START:
Call_winmain
Invoke EXITPROCESS, NULL
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Main window program
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
_WinMain Proc
Local @stwcmain: WNDCLASSEX
Local @stmsg: msg
Local @haccelerator
Invoke INITCOMMONCONTROLS
Invoke getModuleHandle, NULL
Mov Hinstance, EAX
Invoke Loadicon, Hinstance, IDI_MAIN
MOV Hicon, EAX
Invoke loadmenu, hinstance, idm_main
Mov Hmenu, EAX
************** Register window **************************************** **********
Invoke loadCursor, 0, IDC_ARROW
Mov @ stwcmain.hcursor, EAX
Mov @ stwcmain.cbsize, sizeof wndclassex
Mov @ stwcmain.hiconsm, 0
Mov @ stwcmain.style, cs_hredraw or cs_vredraw
Mov @ stwcmain.lpfnwndproc, Offset WNDMAINPROC
Mov @ stwcmain.cbclsextra, 0
Mov @ stwcmain.cbwndextra, 0
Mov Eax, Hinstance
Mov @ stwcmain.hinstance, EAX
Mov @ stwcmain.hicon, 0
Mov @ stwcmain.hbrbackground, color_window 1
Mov @ stwcmain.lpszclassname, offset szclassname
Mov @ stwcmain.lpszMenuname, 0
Invoke registerclassex, addr @stwcmain; *************************************************************************************************************************************************** *************
Invoke CreateWindowex, WS_EX_CLIENTEDGE, /
Offset szclassname, Offset Szcaptionmain, /
WS_OVERLAPPEDWINDOW OR WS_VSCROLL or WS_HSCROLL, /
100, 100, 550, 300, /
NULL, HMENU, HINSTANCE, NULL
Invoke ShowWindow, Hwinmain, SW_SHOWNORMAL
Invoke UpdateWindow, HwinMain
************** Message loop ***************************************** ***********
Invoke loadaccelerators, hinstance, ida_main
Mov @ Haccelerator, EAX
.While true
Invoke GetMsg, NULL, 0, 0
.break .if eax == 0
Invoke TranslateAccelerator, hwinmain, @ Haccelerator, Addr @stmsg
.IF EAX == 0
Invoke TranslateMsg, Addr @stmsg
Invoke DispatchMessage, Addr @STMSG
.endif
.endw
RET
_WinMain ENDP
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
WNDMAINPROC PROC Uses EBX EDI ESI, /
HWnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD
Local @stpos: Point
MOV EAX, UMSG
.IF EAX == WM_CREATE
Mov Eax, HWnd
Mov Hwinmain, EAX
Call_init
*********************************************************** *******************
.ELSEIF EAX == WM_COMMAND
.IF lparam == 0
Mov Eax, WPARAM
Movzx Eax, AX
.IF eax == idm_exit
Call_quit
.ELSEIF EAX == IDM_TOOLBAR
XOR dwflag, f_toolbar
Call_Menustatus
.ELSEIF EAX == IDM_TOOLBARTEXT
XOR dwflag, f_toolbartext
Call_Menustatus
.ELSEIF EAX == IDM_INPUTBAR
XOR dwflag, f_inputbar
Call_Menustatus
.ELSEIF EAX == IDM_STATUSBAR
XOR DWFLAG, F_STATUSBARCALL _MENUSTATUS
.lse
_Debug "Menu Command", "Command ID", EAX
.endif
.endif
*********************************************************** *******************
.ELSEIF EAX == WM_SYSCOMMAND
Mov Eax, WPARAM
Movzx Eax, AX
.IF EAX == idm_help || Eax == idm_about
_Debug "Menu Command", "Command ID", EAX
.lse
Invoke DefWindowProc, Hwnd, UMSG, WPARAM, LPARAM
RET
.endif
*********************************************************** *******************
Press a popup menu when pressing right click
*********************************************************** *******************
.ELSEIF EAX == WM_RBUTTONDOWN
Invoke getcursorpos, addr @stpos
Invoke TRACKPOPUPMENU, HSUBMENU, TPM_LEFTALIGN, @ stpos.x, @ stpos.y, null, hwnd, null
*********************************************************** *******************
.ELSEIF EAX == WM_Close
Call_quit
*********************************************************** *******************
.lse
Invoke DefWindowProc, Hwnd, UMSG, WPARAM, LPARAM
RET
.endif
*********************************************************** *******************
Note: After WndProc processes the Windows message, you must return 0 in Eax.
But the return value after the DEFWINDOWPROC cannot be changed, otherwise the window
; Will not be displayed!
*********************************************************** *******************
XOR EAX, EAX
RET
WNDMAINPROC ENDP
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Main window control subroutine
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Folder
Local @HSYSMENU
Invoke SendMessage, HwinMain, WM_SETITION, ICON_SMALL, HICON
*********************************************************** *******************
; Popup menu to use the submenu to implement
*********************************************************** *******************
Invoke GetSubmenu, Hmenu, 1
Mov Hsubmenu, EAX
Call_Menustatus
*********************************************************** *******************
; Add a menu item in the system menu
*********************************************************** *******************
Invoke Getsystemmenu, Hwinmain, False
Mov @ hsysmenu, EAX
Invoke appendmenu, @ hsysmenu, mf_separator, 0, null
Invoke appendmenu, @ hsysmenu, mf_string, idm_help, offset szmenuhelp
Invoke appendmenu, @ hsysmenu, mf_string, idm_about, offset szmenuabout
RET
_Init ENDP
*********************************************************** *******************
; Set the status of the corresponding menu item according to the flag bit
*********************************************************** *******************
_Menustatus Proc
Test dwflag, f_inputbar
.IF ZERO?
Invoke Checkmenuitem, Hmenu, IDM_INPUTBAR, MF_UNCHECKED
.lse
Invoke checkmenuitem, hmenu, IDM_INPUTBAR, MF_CHECKED
.endif
Test dwflag, f_toolbar
.IF ZERO?
Invoke Checkmenuitem, Hmenu, IDM_Toolbar, MF_unchecked
.lse
Invoke Checkmenuitem, Hmenu, IDM_Toolbar, MF_CHECKED
.endif
Test dwflag, f_toolbartext
.IF ZERO?
Invoke CheckmenuItem, Hmenu, IDM_Toolbartext, MF_unchecked
.lse
Invoke CHECKMENUITEM, HMENU, IDM_TOOLBARTEXT, MF_CHECKED
.endif
Test dwflag, f_statusbar
.IF ZERO?
Invoke CHECKMENUITEM, HMENU, IDM_STATUSBAR, MF_UNCHECKED.ELSE
Invoke Checkmenuitem, Hmenu, IDM_STATUSBAR, MF_CHECKED
.endif
RET
_Menustatus Endp
*********************************************************** *******************
_Quit Proc
Invoke DestroyWindow, HwinMain
Invoke PostquitMessage, NULL
RET
_Quit ENDP
*********************************************************** *******************
End Start
Procedure analysis
Let's simply analyze this program. First of all, this program and the simplest window program of the previous section are the message loop, as follows:
.While true
Invoke GetMsg, NULL, 0, 0
.break .if eax == 0
Invoke TranslateAccelerator, hwinmain, @ Haccelerator, Addr @stmsg
.IF EAX == 0
Invoke TranslateMsg, Addr @stmsg
Invoke DispatchMessage, Addr @STMSG
.endif
.endw
The translateAccelerator in the loop is used to determine whether the message stored in the MSG structure is a keyboard message. If so, it looks for the accelerator key table corresponding to the handle @haccelerator. If a match is found, then it will send it to the window with the command ID WM_COMMAND message, return non-0 value, indicating that the message has been processed, no need to call the following TranslateMessage and DispatchMessage, if not, then it will return 0, the message loop continues. In addition, the pop-up menu is to be explained, in the program, we respond to the WM_RBUTTONDOWN message, then press the right button, then call GetCursorpos to get the current mouse coordinate, then use TrackPopupMenu to pop up a menu on the mouse position, but in the resource file, " The pop-up menu cannot be directly defined, so in the initialization section, we use the GetSubMenu to remove the handle of the pop-up submenu for TRACKPOPUPMENU. 6. Use of toolbars and status bar
Toolbar and status bar
The toolbar and status bar are also an integral part of the Windows standard interface, and the toolbar is usually located below the menu bar. The above is some system defined or its own defined pictures, which can display this button. The status bar is typically located at the bottom of the window to display some information in the program run. The toolbar and status bar are two universal controls for the Windows system. You can create them through two dedicated APIs or using CreateWindowEx to use CreateWindowEx to create them to create them. These two APIs are CreateToolbarex and CreateStatusWindow. Let's take them below. CreateToolbarex's statement is:
HWND CREATOOLBAREX
HWND HWND,
DWORD WS,
UINT WID,
INT NBITMAPS,
Hinstance HBminst,
UINT WBMID,
LPCTBB / LPBUTTONS,
Int inumbuttons, int DXButton,
Int Dybutton,
Int dxbitmap,
INT DYBITMAP,
Uint ustructsize}
In its parameter, hwnd is the handle of the parent window (that is, our main window), WS is the style of the toolbar, can be synthesized, such as WS_Visible is a visible, tbstyle_flat means a flat button, WS_Border means a side line, etc. Specific manual can be seen. WID is the logo of the toolbar, nbitmaps is the number of pictures of the definition button, because if you want to use your own picture, all the images are going to be in the same line, then you specify the number of the middle, HBminst is included The resource handle of the system image has been defined. When you don't want to draw it yourself, use the memory standard picture, generally containing the Hinstance of these images has been defined as hinst_commctrl in widnows.inc, the same WBMID is generally idb_std_small_color, indicating that the big picture is still small Pictures, etc. Next is the data structure of the definition button, the command number, picture number, and other properties of each button are defined in the middle, the structure is as follows:
TBButton Struct
IBITMAP DWORD?
IDCOMMAND DWORD?
FSSTATE BYTE?
FSStyle Byte?
BRESERVED BYTE 2 DUP (?)
DWData DWORD?
Istring DWORD?
TBButton Ends
Where each structure defines a button, IBITMAP is the image ID, IDCommand is the command number of the button. When you press the button, you will appear in the WPARAM of the WM_COMMAND message, you can know which button is Press. FSState is the initial state of the button, such as TBState_Pressed is already pressed, see more, fsStyle is a style. The declaration of CreateStatusWindow in the status bar is as follows:
HWND CREATESTATUSWINDOW
Long Style,
LPCTSTR LPSZTEXT,
HWND HWNDPARENT,
Uint WID
);
Style is the style of the status bar, and LPSZText points to the initialization of the text to display the text on the status bar, you can point to NULL. HWndParent is the handle of the parent window. The WID is the window ID.
Use the source program for toolbars and status bar
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Whether to include debug code
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> DEBUG = 1
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
PROGRAMMED by Luo Yunbin, Bigluo@telekbird.com.cn
; Website: http://asm.yeah.net
Luoyunbin's Win32 ASM Page (Luo Yunbin's Programming Park)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
; Version Information
; Toolbar and Status Bar Test Program Ver 1.0
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.386
.Model flat, stdcall
Option Casemap: None; Case Sensitive
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Include data
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Folder Windows.inc
INCLUDE User32.inc
INCLUDE KERNEL32.INC
INCLUDE COMCTL32.INC
INCLUDE COMDLG32.INC
INCLUDE GDI32.INC
INCLUDELIB USER32.LIB
IncludeLib kernel32.lib
INCLUDELIB COMCTL32.LIB
INCLUDELIB COMDLG32.LIB
IncludeLib GDI32.LIB
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
; EQU data
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
IDI_MAIN EQU 1000; icon
IDM_MAIN EQU 4000; Menu
IDM_TOOLBAR EQU 4001
IDM_STATUSBAR EQU 4002
IDM_EXIT EQU 4003
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Data segment
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>
Hinstance DD?
HwinMain DD?
HMENU DD?
Hicon DD?
HTOOLBAR DD?
HSTATUSBAR DD?
SZBuffer DB 256 DUP (?)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Data segment
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.DATA
SzclassName DB "Toolbar Template", 0
SZCAPTIONMAIN DB 'Toolbar and Status Bar Test - Luo Yunbin', 0
DWFLAG DD F_TOOLBAR OR F_STATUSBAR
*********************************************************** *******************
Sign Definition
F_toolbar EQU 00000001B
F_statusbar EQU 00000010B
Sttoolbar Tbbutton
TBButton <0, 0, TBSTATE_ENABED, TBSTYLE_SEP, 2 DUP (0), - 1>
TBButton
TbButton
TBButton <0, 0, TBSTATE_ENABED, TBSTYLE_SEP, 2 DUP (0), - 1>
TBButton
Tbbutton
Num_Buttons EQU 7; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Code segment
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.code
IF Debug
INCLUDE Debug.asm
ENDIF
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Procedure
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Start:
Call_winmain
Invoke EXITPROCESS, NULL
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Main window program
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Folder
Local @stwcmain: WNDCLASSEX
Local @stmsg: msg
*********************************************************** *******************
If it is already running, activate the running process
*********************************************************** *******************
Invoke Findwindow, Offset SzclassName, NULL
.IF EAX! = NULL
Invoke ShowWindow, Eax, SW_SHOWNORMAL
Invoke EXITPROCESS, NULL
.endif
Invoke INITCOMMONCONTROLS
Invoke getModuleHandle, NULL
Mov Hinstance, EAX
Invoke Loadicon, Hinstance, IDI_MAIN
MOV Hicon, EAX
Invoke loadmenu, hinstance, idm_main
Mov Hmenu, EAX
************** Register window **************************************** **********
Invoke loadCursor, 0, IDC_ARROW
Mov @ stwcmain.hcursor, EAX
Mov @ stwcmain.cbsize, sizeof wndclassex
Mov @ stwcmain.hiconsm, 0
Mov @ stwcmain.style, cs_hredraw or cs_vredraw
Mov @ stwcmain.lpfnwndproc, Offset WNDMAINPROC
Mov @ stwcmain.cbclsextra, 0
Mov @ stwcmain.cbwndextra, 0
Mov Eax, Hinstance
Mov @ stwcmain.hinstance, EAX
Mov @ stwcmain.hicon, 0
Mov @ stwcmain.hbrbackground, color_btnface 1
Mov @ stwcmain.lpszclassname, offset szclassname
Mov @ stwcmain.lpszMenuname, 0
Invoke registerclassex, addr @stwcmain
; ************** Establish an output window ****************************************** *********
Invoke CreateWindowex, Null, /; WS_EX_CLIENTEDGE, /
Offset szclassname, Offset Szcaptionmain, /
WS_OVERLAPPEDWINDOW, /; or WS_VSCROLL or WS_HSCROLL, /
50, 50, 550, 350, /
NULL, HMENU, HINSTANCE, NULL
Invoke ShowWindow, Hwinmain, SW_SHOWNORMAL
Invoke UpdateWindow, HwinMain; ************** Message loop ************************************ ****************
.While true
Invoke GetMsg, NULL, 0, 0
.break .if eax == 0
Invoke TranslateMsg, Addr @stmsg
Invoke DispatchMessage, Addr @STMSG
.endw
RET
_WinMain ENDP
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
WNDMAINPROC PROC Uses EBX EDI ESI, /
HWnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD
MOV EAX, UMSG
.IF EAX == WM_CREATE
Mov Eax, HWnd
Mov Hwinmain, EAX
Call_init
*********************************************************** *******************
.ELSEIF EAX == WM_SIZE
Invoke SendMessage, Hstatusbar, UMSG, WPARAM, LPARAM
Invoke SendMessage, Htoolbar, UMSG, WPARAM, LPARAM
*********************************************************** *******************
.ELSEIF EAX == WM_COMMAND
Mov Eax, WPARAM
Movzx Eax, AX
.IF eax == idm_exit
Call_quit
.ELSEIF EAX == IDM_TOOLBAR
XOR dwflag, f_toolbar
Call_AranGewindow
.ELSEIF EAX == IDM_STATUSBAR
XOR dwflag, f_statusbar
Call_AranGewindow
.lse
_Debug "Menu and Toolbar Command", "Command ID", EAX
.endif
*********************************************************** *******************
.ELSEIF EAX == WM_Close
Call_quit
*********************************************************** *******************
.lse
Invoke DefWindowProc, Hwnd, UMSG, WPARAM, LPARAM
RET
.endif
*********************************************************** *******************
Note: After WndProc processes the Windows message, you must return 0 in Eax.
However, the return value after DEFWINDOWPROC cannot be changed, otherwise the window will not be displayed!
*********************************************************** *******************
XOR EAX, EAX
RET
WNDMAINPROC ENDP
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Main window control subroutine
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
_Init proc
Invoke SendMessage, HwinMain, WM_SETITION, ICON_SMALL, HICON
Invoke CreateToolbarex, HwinMain, /
WS_VISible or WS_CHILD or TBSTYLE_FLAT or WS_BORDER, /
1,0, hinst_commctrl, idb_std_small_color, offset attoolbar, /
Num_Buttons, 0,0,0,0, sizeof tbutton
Mov Htoolbar, EAX
Invoke CreateStatusWindow, WS_CHILD or WS_Visible, Null, Hwinmain, 2
Mov Hstatusbar, EAX
Call_AranGewindow
RET
_Init ENDP
*********************************************************** *******************
_Quit Proc
Invoke DestroyWindow, HwinMain
Invoke PostquitMessage, NULL
RET
_Quit ENDP
*********************************************************** *******************
_ArrangeWindow Proc
Local @STRECT: RECT
Local @stRectTemp: Rect
Local @dwwidth: DWORD
Test dwflag, f_toolbar
.IF ZERO?
Invoke ShowWindow, Htoolbar, SW_HIDE
Invoke Checkmenuitem, Hmenu, IDM_Toolbar, MF_unchecked
.lse
Invoke ShowWindow, HTOOLBAR, SW_SHOW
Invoke Checkmenuitem, Hmenu, IDM_Toolbar, MF_CHECKED
.endif
Test dwflag, f_statusbar
.IF ZERO?
Invoke ShowWindow, Hstatusbar, SW_HIDE
Invoke CHECKMENUITEM, HMENU, IDM_STATUSBAR, MF_UNCHECKED
.lse
Invoke ShowWindow, Hstatusbar, SW_SHOW
Invoke Checkmenuitem, Hmenu, IDM_STATUSBAR, MF_CHECKED
.endif
RET
_ArrangeWindow Endp
*********************************************************** *******************
End Start
Program analysis and points
In the toolbar and status bar program, you should pay attention to the toolbar and status bar without changing your own adjustment position and size with the size of the porn, so you can move and adjust them in the WM_SIZE message of the parent window. Simply pass the WM_SIZE message to them. Don't calculate yourself.
.ELSEIF EAX == WM_SIZE
Invoke SendMessage, Hstatusbar, UMSG, WPARAM, LPARAM
Invoke SendMessage, Htoolbar, UMSG, WPARAM, LPARAM
In addition, the toolbar and status bar are also a sub-window, so if you want to hide or display them, you can use the standard showWindow to process. 7. Subcort for control
Control subsystem
Speaking of class, everyone may think about C immediately, the class is first proposed in C, but this concept is still applicable in Win32ASM, because the idea of the class is like this: first assume a different attribute When a new object of a new object is somewhat different, the other attributes are exactly the same, then in addition to handling this property, other code can be used to use the code of the previous object. In a specific application, I will give an example. For example, we define a "edit" control, then this control is confirmed by Windows, because its window process is inside the Windows system, but if we want to make a "Edit" control for syntax checking, in addition to the code of the grammatical check, have to write a lot of code to realize the old "Edit" control? The answer is of course negative. In fact, we can intercept the WM_CHAR message of a standard "edit" control, check the key to the key and proceed, the other messages can be passed to the original window process. Drawing is as follows:
Before childification: Windows => Edit control window process
After childification: windows => Our process code => Edit control window process
There is a function in Windows API to implement this feature, that is, SETWINDEXLONG PROTO HWND, NINDEX, DWNEWLONG, parameter means hwnd is the window handle you want to change, NINDEX is what properties we have to change the window, it The value can be a GWL_EXSTYLE: Change the window style, GWL_WndProc: Set the new process of setting up the window, which is what we are interested, and GWL_USERDATA This is a 32-bit data of the window customized. Dwnewlong is a new value, and an API is used to call the original window process, called CallWindWoproc Proto LpprevwndFunc, HWND, MSG, WPARAM, LPARAM. We have the following procedure when using: Set the address of our own code with setwindowlong, hwnd, gwl_wndproc, addr _newprocaddress, the API returns the original process address with setWindowlong, HWND, GWL_USERDATA, EAX to save the original process address in custom data in. In this way, all messages will be sent first to our process, then in our own process: the message to be processed, if the original process is not desired, then returns. For your own messages, call the original window procedure and return the return value. The method is: Use Invoke GetWindowlong, HWND, GWL_USERDATA to remove the original process address saved in the custom data with invoke callwindowproc, eax, hwnd, umsg, wparam, lparam call the original process uint ustructsize}
This section provides a source program. It is the URL connection process of the text in the Dialog box. We see the text in the program is blue, there is an underscore, then the mouse moves to the above, Like the super knot in the browser, and press it automatically connected to the website, think about it, we don't have a standard control or API to achieve such a feature, because this is a text, so we can Text is subcatename, handle its WM_LBUTTONUP message to implement the function of automatically connecting to the website; handle the WM_SETCURSOR message to move the mouse to the change cursor above, the specific source program is as follows:
Source program - resource file
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
********************************************************
#include
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
#define idi_main 1000
#define idc_handle 2000
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
; Dialog box 3000
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
#define DLG_ABOUT 3000
#define id_email 3001
#define id_homepage 3002
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Resource definition begins
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Idi_main icon "main.ico"
IDC_Handle Cursor "Handle.cur"
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
DLG_ABOUT DIALOG Discardable 50, 50, 160, 30
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
Caption "URL Joint Text Demo - BY Luo Yunbin"
Font 9, "Song"
Begin
LText "My Home:", -1, 5, 5, 54, 9
LText "http://asm.yeah.net", ID_HomePage, 55, 5, 80, 9
LText "My E-mail:", -1, 5, 17, 54, and 9
LText "Bigluo@telekbird.com.cn", ID_EMAIL, 55, 17, 95, 9
End
Source program - assembly source file
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Whether to include debug code
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Debug = 0
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Folder
; Website: http://asm.yeah.net
Luoyunbin's Win32 ASM Page (Luo Yunbin's Programming Park)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
; Version Information
Window Subclassification Demo Ver 1.0
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.386
.Model flat, stdcall
Option Casemap: None; Case Sensitive
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Include data
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
INCLUDE Windows.inc
INCLUDE User32.inc
INCLUDE KERNEL32.INC
INCLUDE COMCTL32.INC
INCLUDE COMDLG32.INC
Include shell32.inc
INCLUDE GDI32.INCINCINCLUDELIB USER32.LIB
IncludeLib kernel32.lib
INCLUDELIB COMCTL32.LIB
INCLUDELIB COMDLG32.LIB
IncludeLib shell32.lib
IncludeLib GDI32.LIB
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
; EQU data
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
IDI_MAIN EQU 1000; icon
IDC_Handle EQU 2000; Handle Cursor
DLG_ABOUT EQU 3000; Dialog - About
ID_EMAIL EQU 3001
ID_HOMEPAGE EQU 3002
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Data segment
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.DATA?
Hinstance DD?
Hicon DD?
SZBuffer DB 256 DUP (?)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Folding
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
.DATA
HCURSORHANDLE DD?
SzhomePage DB "http://asm.yeah.net", 0
Sizemail DB "Mailto: Bigluo@telekbird.com.cn"
DB "? Subject = 嗨! I like your program!", 0
.code
IF Debug
INCLUDE Debug.asm
ENDIF
*********************************************************** *******************
; Window program about the super connection in the dialog
*********************************************************** *******************
_ HyperLinkProc Proc HWnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD
MOV EAX, UMSG
.IF EAX == WM_LButtonup
Invoke getdlgctrlid, hwnd
.IF eax == id_homepage
Invoke shellexecute, 0, 0, offset szhomepage, 0, 0, 0
.ELSEIF EAX == ID_EMAIL
Invoke Shellexecute, 0, 0, Offset Szemail, 0, 0, 0
.endif
.ELSEIF EAX == WM_NCHITTEST
; Return the WM_NCHITTEST to TRUE to receive the mouse action, implement the function!
Mov Eax, True
RET
.ELSEIF EAX == WM_SETCURSOR
Invoke setCursor, HcursorHandle
.lse
Invoke GetWindowlong, HWnd, GWL_USERDATA
Invoke CallWindowProc, EAX, HWND, UMSG, WPARAM, LPARAM
RET
.endif
XOR EAX, EAX
RET
_HyperLinkProc ENDP
*********************************************************** *******************
; Dialog box main program
*********************************************************** ****************** AboutDialogproc Proc Uses EBX EDI ESI, /
HWnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD
Local @stwindow: Rect
Local @dwwidth: dWord, @ dwheight: dword
Local @HWINTEMP: DWORD
Local @stfont: logfont, @ hfontoutput: DWORD
MOV EAX, UMSG
.IF EAX == WM_Close
Invoke EndDialog, Hwnd, Null
.ELSEIF EAX == WM_INITDIALOG
Invoke getModuleHandle, NULL
Invoke LoadCursor, Eax, IDC_Handle
Mov HcursorHandle, EAX
Invoke getdlgitem, hwnd, id_homepage
Mov @ hwintemp, eax
Invoke setWindowlong, @ hwintemp, gwl_wndproc, addr _hyperlinkproc
Invoke setWindowlong, @ hwintemp, gwl_userdata, eax
Invoke getdlgitem, hwnd, id_email
Mov @ hwintemp, eax
Invoke setWindowlong, @ hwintemp, gwl_wndproc, addr _hyperlinkproc
Invoke setWindowlong, @ hwintemp, gwl_userdata, eax
.ELSEIF EAX == WM_CTLCOLORSTATIC
Invoke Getdlgctrlid, LPARAM
.IF eax == id_homepage || eax == id_email
Invoke SendMessage, LParam, WM_GETFONT, 0, 0
Mov @ hfontoutput, EAX
Invoke getObject, @ HFONTOUTPUT, SIZEOF logfont, addr @stfont
Mov @ stfont.lfunderline, True
Invoke CreateFontIndirect, Addr @stfont
Mov @ hfontoutput, EAX
Invoke SelectObject, WPARAM, EAX
Invoke SetTextColor, WParam, Blue
Invoke Getsyscolor, Color_Menu
Invoke setbkcolor, WPARAM, EAX
Invoke deleteObject, @ HFONTOUTPUT
*********************************************************** *******************
Be careful here to return the return value of the stockOject, otherwise the color cannot be displayed
*********************************************************** *******************
Invoke GetStockObject, Hollow_brush
.lse
Mov Eax, False
RET
.endif
RET
.lse
*********************************************************** *******************
Note: After the message processing of the dialog box, you want to return True, for the unprocessed message; return false
*********************************************************** *******************
Mov Eax, False
RET
.endif
Mov Eax, True
RET
AboutDialogProc ENDP
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Procedure
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>
Start:
Invoke INITCOMMONCONTROLS
Invoke getModuleHandle, NULL
Mov Hinstance, EAX
Invoke Dialogboxparam, Hinstance, DLG_ABOUT, /
NULL, OFFSET ABOUTDIALOGPROC, DLG_ABOUT
Invoke EXITPROCESS, NULL
*********************************************************** *******************
End Start
Program analysis and points
In the resource, we define two text boxes, ID_HomePage and ID_Email, in the initdialog message of the process of the main dialog, we use Getdlgitem to take their hwnd, then subclass, we put new processes Set to _hyperlinkproc
Invoke getdlgitem, hwnd, id_homepage
Mov @ hwintemp, eax
Invoke setWindowlong, @ hwintemp, gwl_wndproc, addr _hyperlinkproc
Invoke setWindowlong, @ hwintemp, gwl_userdata, eax
Invoke getdlgitem, hwnd, id_email
Mov @ hwintemp, eax
Invoke setWindowlong, @ hwintemp, gwl_wndproc, addr _hyperlinkproc
Invoke setWindowlong, @ hwintemp, gwl_userdata, eax
Then in the new process, the WM_LBUTTONUP message (left mouse button release) is detected using the shellexecute API to connect to the website, detect WM_NCHITTEST to receive the text control message, detect the WM_SETCURSOR message to set the cursor to hand shape, for these Messages other than the message we do not process, then use CallWindowProc to call the original process for processing. .IF EAX == WM_LButtonup
Invoke getdlgctrlid, hwnd
.IF eax == id_homepage
Invoke shellexecute, 0, 0, offset szhomepage, 0, 0, 0
.ELSEIF EAX == ID_EMAIL
Invoke Shellexecute, 0, 0, Offset Szemail, 0, 0, 0
.endif
.ELSEIF EAX == WM_NCHITTEST
; Return the WM_NCHITTEST to TRUE to receive the mouse action, implement the function!
Mov Eax, True
RET
.ELSEIF EAX == WM_SETCURSOR
Invoke setCursor, HcursorHandle
.lse
Invoke GetWindowlong, HWnd, GWL_USERDATA
Invoke CallWindowProc, EAX, HWND, UMSG, WPARAM, LPARAM
RET
.endif