"Programming Master Proverbs" after reading # 3

zhaozj2021-02-08  231

After a few years, I have also seen a lot of things. Sometimes I want to write something, but I always feel a lot of clues, and I have not had a pen. Recently, I have turned a "programming master rumor", and suddenly wanted to write something, right to write something in the form of reading notes. The release "rumor" on the equity is the following is the I'm of myself. I hope everyone can advise, but they don't have to be, thank you. Note: This part involves the third chapter of "Proverbs".

All message queues look into the module of the user32, but each application has a USER32 because each application starts from 4000000B, so that each getMessage and PeekMessage are handling events. In fact, each getMessage will become a WaitsingleMessage. When there is an event, it will be processed directly, nor does it help. ============================================================================================================================================================================================================= ================================ Is there a USER32 for each program, I think it is likely to be like this, because I used Win32DASM to negotiate a Win32 console program, and did not find any function calls from User32.dll. Of course, is it not very confident that the User32.dll mappled the program's address space in the runtime system. I don't have it. As for "rumors", each program is starting from 400000B, so there is user32, I can't think of what causal relationship. In fact, GetMessage or PeekMessage is not in processing the message, but is responsible for removing the message from the message queue of the current thread. After calling the translateMessage process, then call the DISPATCHMESSAGE to send the message to the corresponding window handler. The scheduling of the application does not require the application is not because the message does not need to be scheduled, but the system is internally, such as synchronization, scheduling and other operations. For example, when you call sendMessage, if the current thread is a thread that creates a window, SendMessage will call the window function directly to process the message. If it is not the same thread, then the system will hang the current thread, know the goal After the thread accepts the message sent, the SendMessage call of the current thread will return. As a result, the system has made a lot of efforts to support the message system after the scene, thereby simplifying the application. Also, the window handling function is reusable, in the last part of the article, I will give a typical Win32 program to illustrate these issues.

You should complete your own message processing, each program is independent, so you have to use the undercale core to switch between the page. ============================================================================================================================================================================================================= ================================ Oh, I can't see any causal relationship. The independence of the program is inevitable, which is one of the basic features of the modern operating system. As for this independence, it is not necessarily implemented by the CPU paging mechanism. Only the segmentation function of the CPU is enabled, the independence of the process should be implemented. Does the page switching do not need to be realized in the kernel, this is also something that does not need to explain. Most of the instructions involved in the page are most privileged, if you can perform these instructions in the application, then the operating system is not Privilege, the application wants to whole the operating system is easy, just like the past DOS. Other programs will be cut when a program is cut. When switching, the entire message queue is switched out. Therefore, the processing of the entire message is very simple. ============================================================================================================================================================================================================= ================================ This is really unclear, I don't know the so-called "cut", "cut out "What means. It also does not see what the causal relationship is referring to. The simplification of the application message processing is mainly to be a lot of things for user32.dll behind the scenes. Specific description You can find the answer in the book "Programming Applications for Microsoft Windows". In this book, everyone can see some of the system behind the scene.

Note: Honestly, Microsoft is really trouble, what is covered. Isn't it ok for the code? Or don't do it, you can also have a detailed document. Many documents in MSDN are also included. If you want to know more, you will use the debugger yourself, just a word, "tired". Oh, of course, now there are many big cows published their own research on the Internet. The benefit of the benefit :-) Remember that when I first touched Linux, I feel so good. Almost all have source code, I feel that the time to develop things is far less than the development of Windows. I think, when I don't have to take a book such as "undocument dos secretes", "undocument winnt secrets", the majority of peers happy days are coming :-) Remember before WinXP DDK released, domestic and foreign websites How to have a lot of intermedia driver write a virtual network card, and it seems to have no successful solution. After the XP DDK came out, there was an example, and all the problems were solved. Is there so many programmers on the Internet not as Microsoft smart? ! Fortunately, MFC is given to source code. I think if I didn't give the source code, the vast Visual C programmers still don't know how to get to Microsoft!

As can be seen from the MSG structure, each message is corresponding to one window. The USER module is a management window, and a message queue in each window is usually. ...... When you use SendMessage to send a message in the program design, you will clearly specify the window handle. After running this function, you will put the message in the message queue of this window. ============================================================================================================================================================================================================= ================================ From the MSG structure, it seems that each message should correspond to one window. However, the HWND HWND related to the MSG structure and the window can be 0. Then, another and message-related function PostthReadMessage does not require a window handle, but a thread handle. In fact, the message queue should be a thread, not a window. SendMessage a very important feature is that it is not a simple message to the message queue to go, according to MSDN say, If the specified window was created by the calling thread, the window procedureis called immediately as a subroutine.If the specified window was CREATED BY ADIFFERENT Thread, The System Switches To That Thread and calls the appropriateWindow Procedure. Based on SendMessage, it is possible to invoke the textMessage thread forever. For details, you will refer to "Programming Applications for Microsoft Windows". This book also introduces several other functions, such as SendMessageTimeout, InsendMessage, you can also directly refer to MSDN. The code posted below is generated by the wizard of the VC. The "Proverbs" only gives the code for the window processing function in the message loop section. It may be to save paper, save money, online, I will post Little, huh, huh.

1 #include "stdafx.h" 2 #include "resource.h" 3 #include 4 5 #define max_loadstring 100 6 7 // Global Variables: 8 Hinstance Hinst; // Current Instance 9 Tchar Sztitle [MAX_LOADSTRING ]; // The title bar text 10 TCHAR szWindowClass [MAX_LOADSTRING]; // The title bar text 11 12 // Foward declarations of functions included in this code module: 13 ATOM MyRegisterClass (hINSTANCE hInstance); 14 BOOL InitInstance (hINSTANCE, int ); 15 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); 16 LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM); 17 18 int APIENTRY WinMain (hINSTANCE hInstance, 19 hINSTANCE hPrevInstance, 20 LPSTR lpCmdLine, 21 int nCmdShow 22 {23 // Todo: Place Code Here. 24 msg msg; 25 Haccel HaccelTable; 26 CHAR STR [256]; 27 Static I = 0; 28 29 // Initialize Global Strings 30 loadingstri ng (hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 31 LoadString (hInstance, IDC_TEST, szWindowClass, MAX_LOADSTRING); 32 MyRegisterClass (hInstance); 33 34 // Perform application initialization: 35 if (! InitInstance (hInstance, nCmdShow)) 36 { 37 Return False; 38} 39 40 HACCELTABLE = loading, (lpctstr) IDC_TESTA); 41 42 // Main Message Loop: 43 While (& MSG, NULL, 0, 0)) 44 {45 if (! TranslateAccelerator " Msg.hwnd, HaccelTable, & MSG) 46 {47 TranslateMessage (& MSG); 48 DispatchMessage (& MSG); 49} 50} 51 52 Return Msg.wparam;

53} 54 55 56 57 // 58 // Function: myregisterclass () 59 // 60 // Purpose: Registers the window class. 61 // 62 // Comments: 63 // 64 // this function and its usage is only necessary if you want this code 65 // to be compatible with Win32 systems prior to the 'RegisterClassEx' 66 // function that was added to Windows 95. It is important to call this function 67 // so that the application will get 'well formed 'small icons associated 68 // with it 69 // 70 ATOM MyRegisterClass (hINSTANCE hInstance) 71 {72 WNDCLASSEX wcex; 73 74 wcex.cbSize = sizeof (WNDCLASSEX); 75 76 wcex.style = CS_HREDRAW | CS_VREDRAW;. 77 wcex .lpfnWndProc = (WNDPROC) WndProc; 78 wcex.cbClsExtra = 0; 79 wcex.cbWndExtra = 0; 80 wcex.hInstance = hInstance; 81 wcex.hIcon = LoadIcon (hInstance, (LPCTSTR) IDI_TEST); 82 wcex.hCursor = LoadCursor (NULL, IDC_ARROW); 83 wcex.hbrbackground = (Hbrush) (C OLOR_WINDOW 1); 84 wcex.lpszMenuName = (LPCSTR) IDC_TEST; 85 wcex.lpszClassName = szWindowClass; 86 wcex.hIconSm = LoadIcon (wcex.hInstance, (LPCTSTR) IDI_SMALL); 87 88 return RegisterClassEx (& wcex); 89} 90 91 // 92 // Function: InitInstance (Handle, Int) 93 // 94 // Purpose: Saves Instance Handle and Creates Main WINDOW 95 / / 96 // Comments: 97 // 98 // In this function, we save the the Instance Handle In A Global Variable and 99 // Create and Display The Main Program Window. 100 // 101 Bool InitInstance (Hinstance Hinstance, INT NCMDSHOW) 102 {103 HWND HWND; 104 105 Hinst =

hInstance; // Store instance handle in our global variable 106 107 hWnd = CreateWindow (szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 108 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 109 110 if (! hWnd) 111 { 112 RETURN FALSE; 113} 114 115 ShowWindow (hwnd, ncmdshow); 116 UpdateWindow (HWND); 117 118 Return True; 119} 120 121 // 122 // Function: WndProc (HWND, Unsigned, Word, Long) 123 ///// 124 // Purpose: Processes Messages for the main window. 125 // 126 // WM_COMMAND - Process the Application Menu 127 // WM_Paint - Paint The Main WINDOW 128 // WM_DESTROY - POST A Quit Message and Return 129 // 130 // 131 LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 132 {133 int wmId, wmEvent; 134 PAINTSTRUCT ps; 135 HDC hdc; 136 TCHAR szHello [MAX_LOADSTRING]; 137 LoadString (hInst, IDS_HELLO, szHello, MAX_LOADSTRING 138 139 Static INT i = 0; 140 Char Str [256]; 141 142 Switch (Message) 143 {144 case wm_command: 145 wmid = loword (wparam); 146 wmevent = HiWord (wparam); 147 // Parse the menu Selections: 148 Switch (wmId) 149 {150 case IDM_ABOUT: 151 DialogBox (hInst, (LPCTSTR) IDD_ABOUTBOX, hWnd, (DLGPROC) About); 152 break; 153 case IDM_EXIT: 154 DestroyWindow (hWnd); 155 break; 156 default: 157 return DefWindowProc ( HWND, Message, WParam, LParam; 158} 159 Break; 160 case wm_paint: 161 HDC = Beginpaint (HWND, & PS); 162 // Todo: Add any Drawing code Here ... 163 Rect RT; 164 getClientRect (hwnd, & rt);

165 DrawText (hdc, szHello, strlen (szHello), & rt, DT_CENTER); 166 EndPaint (hWnd, & ps); 167 break; 168 case WM_DESTROY: 169 PostQuitMessage (0); 170 break; 171 default: 172 return DefWindowProc (hWnd, message, wParam, lParam); 173} 174 return 0; 175} 176 177 // Mesage handler for about box 178 LRESULT CALLBACK About (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 179 {180 switch (message) 181. {182 Case WM_INITDIALOG: 183 RETURN TRUE; 184 185 Case WM_COMMAND: 186 IF (WPARAM) == iDok || Loword (WPARAM) == Idcancel) 187 {188 EndDialog (HDLG, LOWORD (WPARD (WPARAM)); 189 Return True 190} 191 Break; 192} 193 Return False; 194} A ordinary Win32 GUI program, you only don't go off it, it always exists. Obviously, there is a need for a similar loop to ensure that our programs are always running. Look at the code No. 43: 43 While (GetMessage (& MSG, NULL, 0, 0)) 44 {45 if (! TranslateAccelerator (Msg.hWnd, HaccelTable, & MSG) 46 {47 TranslateMessage (& MSG); & msg 48 DispatchMessage (& MSG); 49} 50} Oh, we found this loop, which is this short 8 line code, keep our program exists in the system, once this loop is broken, then our procedure is launched . As for how to break this loop, go see GetMessage's instructions. (Note: In the ordinary Win32 program, it can be considered that WinMain is the entry point of the program. This 80 line has the meaning of constantly taking the message from the system. After receiving the service processing of the system, send it to the corresponding window process. . This process loops until the program is introduced. This is the so-called "message loop" name.

So where is the window process? Ok, let's take a look at the properties of the window we created, starting from 76 lines: 76 wcex.style = cs_hredraw | cs_vredraw; 77 wcex.lpfnWndProc = (wndProc) WndProc; 78 wcex.cbclsextra = 0; 79 wcex.cbwndextra = 0 ; 80 wcex.hInstance = hInstance; 81 wcex.hIcon = LoadIcon (hInstance, (LPCTSTR) IDI_TEST); 82 wcex.hCursor = LoadCursor (NULL, IDC_ARROW); 83 wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW 1); 84 wcex.lpszMenuName = (LPCSTR) IDC_TEST; 85 wcex.lpszClassName = szWindowClass; 86 wcex.hIconSm = LoadIcon (wcex.hInstance, (LPCTSTR) IDI_SMALL); others we do not care about being the first to see the 77th row, lpfnWndProc what is? According to Hungarian naming method, this is a function pointer! (WndProc) WndProc is a function we define (line 131). So I understand that a function we define is saved in the window structure. Scan the procedure of the previous column, discover (wndproc) WndProc is not called! How is this going? It turns out that this is tells us: There is a function you (application) define and implement it, tell me, then you don't worry, I (system) will call according to the situation. Therefore, in essence, the window function is only a callback function defined by the system. Everyone is used to this callback function, and many places in Windows will define similar callback functions to make you realize. Previously, when using Win32 API directly, it is usually seen in (WndProc) WndProc to see a huge Switch / Case structure in this huge structure to complete the processing of interests. So what do you have? Check MSDN is ok, but I am using the tool of Visual C , SPY . When you open the Message log window in Spy , you can see almost all public messages in the second Tab page, and is divided into classes. I recommend everyone to browse, don't remember, but it is best to have a rough impression, especially comrades programmed with Visual C . We said that the window process can be re-entered, how to prove? The procedure is used in the previous column. First, the above program is explained. The above program uses a standard "Win32 Application" of the Win32 Application of the VC, and the result of running is in a window to print Chu "Hello World". Select Help / About in the menu, a "about windows" will pop up. Take a look at the 151st line, here will pop up "about the window", and the Dialogbox is not returned before the pop-up window is not closed.

After we select "About" in the menu, we can pop up this dialog, now dragging this dialog, move in our main order window, we will find that this window will be opened from the covered Hello World Hello World will reappear. What is the problem? There are a few descriptions before answering this question: 1) In our program, only the "Hello World" string will be drawn when responding to WM_PAINT. 2) The system does not save the content of the window customer area, the content of the system client is to draw, that is, when the window covered "Hello World" is removed, the new "Hello World" is still our own painting And this drawing code is only available in the corresponding functions of WM_Paint. OK, integrated above, during the "About Window" event, obviously our program is on Chapter 151, and the code of redrawing the window is in 165 lines, this only an explanation: (wndproc) WndProc before returning (that is DialogBox Returns), (WndProc) WndProc is called to process WM_Paint by the system. That is to say, DispatchMessage will result in the call of (WndProc) WndProc, and the system will also call (WndProc) WndProc when necessary, and the calls of both are asynchronous. So sometimes the abnormal situation of the program may be related to this. Oh, but I haven't encountered this situation. By the way, everyone can look at the value of Hinstance, is 0x400000, like the start address of the program, huh, is it a coincidence, everyone can study it. Also make up the above, the function about is the "About Window" window function, which is passed to the system in the Dialogbox function. The relationship between GDI and DirectDraw ===================== I originally thought that "rumors" will point out the relationship between the two underlying, who knows after reading I didn't see anything else. "Proverbs" is just a simple introduction (in fact, it is not introduced) DirectDraw, and then gives a 24-bit map to 16-bit chart converter. In fact, GDI obviously appears before DirectDraw, and DirectDraw is a soft / hardware specification that Microsoft is a soft / hardware that requires quick access to display devices for easy games, multimedia, etc.. It seems that DirectDraw has been in DirectShow in the latest DirectX SDK. The double buffer technology mentioned in "Proverbs" is very important. DirectX directly supports display buffer switching, we need this technology when we draw animation with GDI or such a slow method such as Javaawt, otherwise it will An annoying screen flicker is a phenomenon. When we design our more big (larger) control, there are two principles that are particularly important.

A thread is an example of executing a program. The thread allows a program to run at the same time than one place, which has some part of multiple CPUs, each CPU executor. In a single processor system, the thread is only in the same time. ============================================================================================================================================================================================================= ============================================================================================================================================================================================================= The thread should be an execution sequence in the application, and Windows is when using CreateTHRead, the most important parameter is "start address", which is actually defined as a function pointer, prototype is DWord WinApi ThreadProc (LPVoid LPParameter) . In the multiprocessor machine, in the case of ideal, each thread runs on a separate CPU, and in a single processor system, the operating system simulates a so-called "simultaneous operation by giving each thread a run time piece. ". But this "simultaneous" is a macro look, in fact, only one thread is run at a certain moment, which is different from the multiprocessor machine. On the multiprocessor's machine, some people suggest that the number of threads that opens up to do not exceed the number of CPUs, and should be unmatched on a CPU on a CPU. There is a matter of particular importance, on a single processor, a thread unless you ask yourself, or you can't assume when you are switched out.

No, each thread itself does not have an SS register and interdependence. In fact, each thread has an address space inside the address space of the process itself. ============================================================================================================================================================================================================= ============================================================================================================================================================================================================= ===== "Proverbs" this sentence does not know how to understand. However, each thread has an independent stack obviously incapacitated, which is one of the basic requirements that the thread mechanism can achieve. According to the discussion in the "Windows Operating System Principle" composed in Yugan, Shi Merlin, each thread is associated with its associated process sharing address space, communication between threads is also directly, through a global variable with lock It can be safely carried out. Threads in GDI conflicts: the main reason for the crash. ================================ For this topic, I wrote a program to test it, tell everyone the result. Say. The program is a dialog-based program that uses VC wizards. Then the program generates 11 threads, each thread, with the DC random drawing line with the dialog window, and random SLEP a small time in each thread, which is 10 milliseconds to 30 milliseconds. I have been running about 10 minutes and have other programs that have been moved on the dialog. The result is that there is no situation in "rumors". If you have a deadlock in the "rumors", please send me a copy, thank you :-)

It is easy to cause conflicts when the thread uses a standard library of C. =============================================================================== Support multithreaded, the most important reason is that there is a global variable in C to. Typical is this Errno, you think, in multithreaded environments, everyone tunes the C library, and errno is a global variable, then once the error happens, then which thread is Errno? At this time, you must link the multi-threaded version of the C library. Therefore, it is easy to cause conflicts when the thread uses a single-threaded C standard library.

When you use _beginthread, use CloseHandle to turn off the thread, these copove global structures will not be released, which has memory leaks. ============================================================================================================================================================================================================= ============================================================================================================================================================================================================= In fact, a correct program does not appear above, otherwise it can only explain how to write the program that has not understood multi-threaded. Why do you say this? If you use _beginthread in the standard C environment, however, the document clearly explains this time to end the thread at _endthread, if you can only show that you are a smart in your own use. In the VC / MFC environment, I will directly instantly AFXBEGINTHREAD or use CWINTHREAD directly, so there is also no problem. In fact, look at the CRT source code of the VC belt: / * Allocate and Initialize a per-thread data structure for the to- * be-created thread. * / If ((PTD = _Calloc_CRT (1, sizeof (struct _tiddata)) = = NULL) Goto error_return; everything is caused by this _calloc_CRT, but said it back, you will not have problems in accordance with the rules. Also a thread will not exit at all, it has been running a loop thread. ================================================= 这里It seems that it is easy to cause misunderstanding, in fact, the thread is one, as for you to end, when it makes it over, it is a programmer's own business. This sentence may misunderstand your neighbors, or explain it.

A kernel32 handle is only valid inside the process itself, and trying to use a process handle to another process. ============================================================================================================================================================================================================= =============================== This sentence is not very accurate, some global unique handles, such as Process Handle, completely Divided by other processes. If the process B knows the handle of the process A, and in the case of permission allows, you can end A thread with TerminateProcess. A true Win32 program does not deplete the CPU time waiting for some time. ============================================================================================================================================================================================================= = In fact, the application does not deplete the CPU time, because the current Windows will not wait for a program to make the control right, but can actively deprive the CPU time film of a program, as long as it is operational The system is considered to be at a time. You can completely let your program while (1); and this time your Winamp will put MP3, no pause. But usually we don't use a loop to detect a sign, especially in the message processing function, to avoid this, because the performance of the message processing function is in appearance is your program "Lost Response". The solution can be a thread to loop or use the Notify mechanism such as Event.

转载请注明原文地址:https://www.9cbs.com/read-1776.html

New Post(0)