Object-oriented programming experiment three basic usage of sduwh sub-windows and controls, resource usage refer to experiment report 2

Collected from the Internet, for reference only

Experiment 3 collected two complete reports, this is the second, and the other one can be found in the previous article of this column.

1 Experimental Requirements
· Overall purpose: understand, message transfer between windows, call stack; master how to make and use cursors, icons, and menus; master how to respond to
menus, how to load and use shortcut menus; understand
GetWindowLong/ Usage of SetWindowLong, GetClassLong/SetClassLong functions.
· Experiment content process:
1. Improve the ChildWin sample program, display window-specific information (window ID number) in the sub-window; try to
draw a rectangle of a specific color in each sub-window
 Refresh processing in the window procedure function of the sub-window Add processing code to the message;
 Use the GetWindowLong function to get the sub-window ID;  Set the information to be displayed in the sub-window according to the sub-window ID (use the wsprintf function to organize the string
to be displayed )  Try to draw a specific color in the sub-window 2. Track message delivery process Set breakpoints at WM_CREATE, WM_PAINT, WM_COMMAND, WM_LBUTTONDOWN of Childwin’s main window process function Set breakpoints at WM_CREATE, WM_PAINT, WM_CHILDWIN, WM_LBUTTONDOWN of Childwin Click  to run the program and view the response process of each breakpoint, so as to understand the order of message delivery 3. Design and implement a soft keyboard









Use the sub-window to realize a soft keyboard (draw a simulated keyboard with the sub-window in the client area of ​​the window), and click
each sub-window with the mouse to input different characters. Displays the entered characters in the window.
4. Create a new project in your own working directory for control testing (you can copy easywin.c of the Easywin project
to the directory of the new project, modify the file name to ctltest.cpp (change the suffix to .cpp), compile, link and make the program
work (including fixing compilation errors)].
5. * Use Button to complete the soft keyboard required by 4*. Compare the differences with the original implementation.
6. Create various types of control sub-windows, including static, edit, listbox, combobox, button, scrollbar,
etc.; add corresponding message processing in the window procedure function of the main window to realize the communication between the main window and the sub-window (
try Set the title/content of the control, get the title/content of the control, and give a
prompt in the main window when the control has operations such as clicking).
7. Same as step 5, create a new project for resource testing.
8. Add new resources: cursor, icon, and display them correctly
 Use the resource editor to edit a cursor (color), pay attention to delete unnecessary image types in resources, otherwise
the cursor may not be displayed correctly.
 Set a hot spot for the cursor
 Edit an icon with a resource editor
 Modify the code of the registered window class so that the program can use the custom cursor and icon normally
 Use the DrawIcon function to add processing to the WM_PAINT message, in
The custom object-oriented programming technology experiment report is displayed in the client area of ​​the window
2
cursors and icons.
 Create another cursor for subsequent experimental steps
9. Add menu
 Create a menu item command in the menu to modify the cursor used by the window, which can be named "ChangeCursor", and the
corresponding ID is assumed to be ID_CHANGECURSOR
 Modify the code of the registered window class, Make the menu can be loaded correctly when the program is running
Another way, by modifying the code of CreateWindow (CreateWindow), the menu can be loaded correctly
10. Increase the menu message response code
Increase the message processing of WM_COMMAND
Refer to Chapter 5 Menu The processing method in the sample code responds to menu commands
 The response to the ID_CHANGECURSOR command is: to change the cursor used by the window, you can use
SetClassLong (hwnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR2 ) ) );
11. Handle the right button of the mouse and add shortcut menu processing
 The menu command issued by the right button is also responded through the WM_COMMAND message. After adding the shortcut menu,
the program should be able to issue the same command through the main menu or the shortcut menu
12. Add the compilation and linking of the project completed in this experiment to the batch file used for program construction, and use the batch file to
automatically build all the projects in Experiment 1, 2, and 3 at one time.

2 Experimental process and results


2.1 Improve the ChildWin sample program, display window-specific information (window
ID number) in the sub-window; try to draw a rectangle of a specific color in each sub-window
As shown in the figure, display the id number and draw a green rectangle

2.2 Tracking the messaging process

1. Set breakpoints at WM_CREATE, WM_PAINT, WM_COMMAND, WM_LBUTTONDOWN of ChildWin's main window process function

·WM_CREATE:

break when window is created


WM_COMMAND:
The program generates an interruption when hitting the child window
 
WM_LBUTTONDOWN:
The program generates an interruption when the left mouse button is pressed

2. Set breakpoints at WM_CREATE, WM_PAINT, WM_CHILDWIN, WM_LBUTTONDOWN of the child window
WM_CREATE:


WM_PAINT:
The main window is drawn and displayed normally, and an interrupt is generated before the sub-window is drawn. Under the process-by-process operation, start from the first sub-window, and draw and display one by one with the cycle of WM_PAINT.
 
WM_CHILDWIN:
When the mouse hits the sub-window, the main window receives a notification message and sends a notification message to WM_CHILDWIN, which generates an interruption
 
WM_LBUTTONDOWN:
 
3. Run the program and check the response process of each breakpoint to understand the order of message delivery :
After setting a breakpoint and performing corresponding debugging, we can know that when the left mouse button hits a sub-window, WM_LBUTTONDOWN of the sub-window generates a response and sends a message to the main window WM_COMMAND, and WM_COMMAND sends a message to the sub-window after confirming that the sub-window is hit WM_CHILDWIN, WM_CHILDWIN sets the child window hit flag to 0 after receiving the message.


2.3 Design and implement a soft keyboard, click each sub-window with the mouse to input different characters, and display the input characters in the window
 

 


2.4 Create a new project for control testing, copy the easywin.c of the Easywin project to the directory of the new project, modify the file name to ctltest.cpp (change the suffix to .cpp), compile, link and make the program work normally (including fix compile errors)
 
 

 

 

 

 

2.5 *Use Button to complete the soft keyboard implementation required by 4*

 


2.6 Create various types of control sub-windows, add corresponding message processing in the window procedure function of the main window to realize the communication between the main window and the sub-window


Create EDIT, LISTBOX, BUTTON windows for testing:
1. The EDIT window can implement text input: 2.
 
The LISTBOX window will pop up a window to display the current option value when a row is clicked:
 
3. The BUTTON window will pop up a window prompt after clicking the left mouse button The button has been pressed:
 
2.7 Create a new project for resource testing
 
2.8 Add new resources: cursor, icon, and display correctly
1. Use the resource editor to edit a cursor (color)
  
2. Set a hot spot for the cursor (hot spot)
 
3. Edit an icon with the resource editor

 

 

 

 

 

 

4. Modify the code of the registered window class so that the program can use the custom cursor and icon normally

 

5. Use the DrawIcon function to add processing to the WM_PAINT message, and display the custom cursor and icon in the client area of ​​the window.

 

6. Create an additional cursor for subsequent experimental steps


 
2.9 Add menu
1. Create a menu item command in the menu to modify the cursor used by the window, which can be named "ChangeCursor", and the corresponding ID is assumed to be ID_CHANGECURSOR
 

 

 

 

2. Modify the code of the registered window class so that the menu can be loaded correctly when the program is running
 


 
3. In another way, by modifying the code of CreateWindow, the menu can be loaded correctly
 
 
2.10 Add menu message response code Add WM_COMMAND message processing, the response to ID_CHANGECURSOR command is: change the cursor menu command ChangeCursor
used by the window
 
After:
 
2.11 Handle the right mouse button and add shortcut menu processing
The menu commands issued by the right button are also responded through WM_COMMAND messages. After adding the shortcut menu, the program should be able to issue the same
 
2.12 This experiment The compilation and linking of the finished project are added to the batch file used for program construction, and all the projects in experiment 1, 2, and 3 are automatically built at one time with the batch file.
 
3 Summary of the experiment
This experiment is much more difficult than the previous two experiments, adding a part that needs to be thought and explored by myself, and it is precisely because of this that I have gained a lot from this experiment: 1. I have a deeper understanding of functions such as
GetWindowLong Understand, from extracting the ID of the child window to drawing a rectangle, through the application of related functions and breakpoint debugging, I have a more thorough understanding of the message notification connection and related operations between the parent window and child windows. The relationship between the parent window and the child window can achieve what you want concisely and effectively.
2. Through the design and implementation of the soft keyboard, I learned more about the selection and release of child windows, and the corresponding operations of the parent window. And in the process of creating the soft keyboard, I also thought more about the layout of the sub-windows. After my own exploration and experimentation, I tried my best to make a more beautiful soft keyboard, and I also gained a kind of achievement in the process of experimenting hard. feel. Looking back, the production of a soft keyboard is not complicated, but it was still a clueless project for me before. The creation of a soft keyboard from scratch has also witnessed the process of learning and accumulating knowledge in the course.
3. The control test part is more an extension of the program examples in the class. It is not difficult. The main knowledge to learn is the structure of each space, how to write in the window, and how to apply it to achieve the desired effect.
4. The resource test is the same as above. With the teacher's patient explanation, most of the functions required by the experiment can be realized in class. In my own after-class experiment, I mainly performed operations such as the application of programs to resources.
5. Compared with the previous two parts, I encountered some difficulties in the menu part. Following the teacher's operation in the class, the establishment and reference of the menu have not been realized. In the realization part of the menu function, according to the experiment, the SetClassLong function can also be realized after several attempts. The relatively time-consuming part lies in the production and use of the shortcut menu, which requires self-study and production. After consulting the information and trying continuously, I finally completed the operation of changing the cursor in the shortcut menu.
6. In general, this experiment is relatively successful. Although it takes a lot of time, most of the projects are completed with my own efforts. I have a deeper understanding of the knowledge of Windows programming. The realization of the project also makes me feel that if I pay, I will be rewarded. But at the same time, due to the slow progress of my experiment, the BUTTON soft keyboard selected as the project has not been realized. In the next experiment, I will work harder, complete the experiment in time, and do every experimental task well.

 

 Appendix: Key Codes

 

 

 

 

Use the GetWindowLong function to get the child window ID;

Set the information to be displayed in the sub-window according to the sub-window ID (use the wsprintf function to organize the string to be displayed)

    int number = GetWindowLong ( hWnd , GWL_ID ); // Get the child window ID

    char string[20];

    wsprintf(string, TEXT("%d"), number);

case WM_PAINT:

DrawText (hdc, string,         // Display sub-window ID number

            -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

Draw a rectangle of a specific color

    HBRUSH hColorPen;

    HGDIOBJ  hGdiobj;

hColorPen = CreateSolidBrush( RGB (10, 100, 100)); // Create a brush and choose a color

    hGdiobj = SelectObject(hdc, hColorPen); // The selected area is drawn with a brush

    Rectangle(hdc, 5, 20, 45, 45);

DeleteObject(hColorPen); // Release the brush

Design and implement a soft keyboard:

#define ROW_NUM 4    // number of rows

#define COL_NUM 16   // Number of columns

INT t = 0; // Global variable t, which becomes 1 when the sub-window is selected for the first time, is used to avoid inputting characters in the initial state of the soft keyboard

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static HWND hChildWnd[ COL_NUM ][ ROW_NUM ];  // child window handle

    static int   nXBox, nYBox;                 // Sub window width and height

    static WORD nChildWin_ID;                 // ID of the hit child window

    static int   nRow, nCol;                   // The position of the hit sub-window (that is, the row and column number)

    int         x, y;

WNDCLASS     wcChild;                      // Child window class

   

switch (message)

{

case WM_CREATE:

...

// Create each tool sub-window similar to the drawing toolbar in the "Drawing" program

for (y = 0; y < ROW_NUM; y++)

            for (x = 0; x < COL_NUM; x++)

            {

                nChildWin_ID = y << 4 | x;             // The child window ID value is equivalent to y * 2^4 +4

                hChildWnd[x][y] = CreateWindow(szChildName, NULL,

                    WS_CHILDWINDOW | WS_DLGFRAME | WS_VISIBLE,

                    0, 0, 0, 0,

                    hWnd,

                    ( HMENU )(nChildWin_ID), // child window id number

                    //0,

                    hInst, NULL);

}

return 0;

case WM_SIZE:

        nXBox = (LOWORD(lParam)*4/5)/ COL_NUM;

        nYBox = (HIWORD(lParam)*2/5) / ROW_NUM;

// When the size of the main window changes, re-determine the position of each sub-window in the client area of ​​the main window

        for (y = 0; y < ROW_NUM; y++)

            for (x = 0; x < COL_NUM; x++)

            {

                MoveWindow(hChildWnd[x][y], (x * nXBox + LOWORD(lParam)/10),

                    (y * nYBox + HIWORD ( lParam ) / 3), nXBox, nYBox, TRUE ); //xy width and height

            }

return 0;

case WM_COMMAND :                // The notification message that the child window is hit

        // Send this message to notify the main window when the sub-window is hit, so that the main window can determine whether another sub-window is hit,

        // If so, send a message to notify the sub-window function to change the state of the previously hit sub-window,

        if (!(LOWORD(wParam) == nChildWin_ID))

        {

            SendMessage (( HWND )hChildWnd[nCol][nRow], WM_CHILDWIN , 0, 0L);

            // Record the new hit child window

            nChildWin_ID = LOWORD(wParam);

            nCol = (nChildWin_ID > 15) ? (nChildWin_ID - 16) : nChildWin_ID;

            nRow = nChildWin_ID >> 4;             

        }

        InvalidateRect(hWnd, NULL, TRUE);

    return 0;

case WM_PAINT:

        if (t)// After a child window is hit, start to draw and display the corresponding character

        {

            HDC         hdc;

            PAINTSTRUCT ps;

            RECT        rect;

            LONG l = 0;

            GetClientRect(hWnd, &rect);

            hdc = BeginPaint(hWnd, &ps);

            int number = nChildWin_ID;

            static char string[100] = { 0 };

            static int n = 0;

            string[n] = number + 65;

            n++;

            DrawText(hdc, string, n, &rect, DT_SINGLELINE);

            EndPaint(hWnd, &ps);

        }

    return 0;

....

   

return DefWindowProc(hWnd, message, wParam, lParam);

} // Function WinProc ends

LRESULT CALLBACK ChildWndProc( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )

{

...

case WM_LBUTTONDOWN:

        // The new child window is hit

        if (GetWindowLong(hWnd, 0) == 0)

        {

            t = 1;

            // Set the child window hit flag to 1

            SetWindowLong(hWnd, 0, 1);

            // Send a message to notify the main window

            SendMessage(GetParent(hWnd), WM_COMMAND,

                //(WPARAM) MAKELONG ((WORD)GetWindowWord (hWnd, GWL_ID), (WORD)0),

                GetWindowLong ( hWnd , GWL_ID ),

                (LPARAM)hWnd);

            // Redraw the client area of ​​the child window

            GetClientRect(hWnd, &rect);

            InvalidateRect(hWnd, &rect, TRUE);

        }

    return 0;

case WM_CHILDWIN :          // The notification message sent by the main window changes the state of the original hit child window

        // Set the child window hit flag to 0

        SetWindowLong(hWnd, 0, 0);

        // Restore the initial display mode of the child window

        GetClientRect(hWnd, &rect);

        InvalidateRect(hWnd, &rect, TRUE);

return 0;

    case WM_PAINT:

        hdc = BeginPaint(hWnd, &ps);

        GetClientRect(hWnd, &rect);

        Rectangle(hdc, 10, 10, 40, 40); // left high right bottom

         for (int j = 0; j < COL_NUM; j++)

            for (int i = 0; i < ROW_NUM; i++) //列数

            {

                char szBuff[50];

                char key = GetWindowLong(hWnd, GWL_ID) + 65;

                wsprintf (szBuff, TEXT ( "%c" ), key); // draw the letters of the subwindow

                DrawText(hdc, szBuff,

                    -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

            }

EndPaint(hWnd, &ps);

return 0;

case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

return DefWindowProc(hWnd, message, wParam, lParam);

} // Function ChildWinProc ends

Create various types of control sub-windows, and add corresponding message processing in the window procedure function of the main window to realize the communication between the main window and the sub-window

#define ITEMCOUNT 5

WCHAR gListItems[ITEMCOUNT][60] = {

    L"MSG msg;",

    L"if (!InitWindow (hInstance, iCmdShow))",

    L"return FALSE;",

    L"GetMessage (&msg, NULL, 0, 0)",

    L"OK"

};

LRESULT CALLBACK WinProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

....

switch (message)

    {

        case WM_CREATE :         // Create message

            hWndEdit = CreateWindow(TEXT("EDIT"),                   //EDIT

                NULL ,                                // no title

                WS_CHILD | WS_VISIBLE | WS_HSCROLL |    // Edit control style

                WS_VSCROLL | WS_BORDER | ES_LEFT |

                ES_MULTILINE | ES_AUTOHSCROLL |

                IS_AUTOVSCROLL ,

                0, 0, 0, 0,

                hWnd ,                                // parent window handle

                ( HMENU )1,                            // Edit control sub-window ID

                (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),

                NULL);

            hWndList = CreateWindow ( TEXT ( "LISTBOX" ),                    //LISTBOX                 NULL ,                                // untitled

                WS_CHILD | WS_VISIBLE | LBS_STANDARD ,   // edit control style

                0, 0, 0, 0,

                hWnd ,                                // parent window handle

                ( HMENU )2,                            // Edit control sub-window ID

                (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),

                NULL);

            hWndButton = CreateWindow(TEXT("BUTTON"),                 //BUTTON

                NULL ,                                // no title

                WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,

                0, 0, 0, 0,

                hWnd ,                                // parent window handle

                ( HMENU )3,                            // Edit control sub-window ID

                (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),

                NULL);

            for (int i = 0; i < ITEMCOUNT; i++)

            {

                SendMessage(hWndList, LB_ADDSTRING, 0, (LPARAM)gListItems[i]);

            }

            return 0;

       

case WM_SIZE:

            MoveWindow(hWndEdit, 0, 0, LOWORD(lParam) / 3, HIWORD(lParam), TRUE);

            MoveWindow(hWndList, LOWORD(lParam) / 3 + 2, 0, LOWORD(lParam) / 3 - 5, HIWORD(lParam), TRUE);

            MoveWindow(hWndButton, 2*LOWORD(lParam)/3+2 , 0, 2*LOWORD(lParam)/3-5 , HIWORD(lParam), TRUE);

    return 0;

case WM_COMMAND:

            WORD w, W1, W2, W3;

            w = LOWORD ( wParam );

            W1 = HIWORD(wParam);

            W2 = LOWORD(lParam);

            W3 = HIWORD ( lParam );

            // Edit control notification message

            if ((LOWORD(wParam)) == 1)

            {

            }

            else if ((LOWORD(wParam)) == 2)

            {

                if (HIWORD(wParam) == LBN_SELCHANGE)

                {

                    WCHAR msg[32];

                    UINT u = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);

                    wsprintf(msg, L"%d", u);

                    MessageBox(hWnd, msg, L"SEL", MB_OK);

                }

            }

            else if ((LOWORD(wParam)) == 3)

            {

                MessageBox ( hWnd , TEXT ( "Button pressed!" ), TEXT ( " Window message" ), MB_OK );

            }

            return 0;

        case WM_DESTROY:

            PostQuitMessage(0);

            return 0;

    }

    // Call the default message handler

    return DefWindowProc (hWnd, message, wParam, lParam);

} // Function WinProc ends

Modify the registration window class code so that the program can use custom cursors and icons normally

    wcMainWnd.hIcon = LoadIcon ( hInstance , MAKEINTRESOURCE ( IDI_ICON1 ));// Icon

    wcMainWnd.hCursor = LoadCursor ( hInstance , MAKEINTRESOURCE ( IDC_CURSOR1 ));//光定

Use the DrawIcon function to add processing to the WM_PAINT message, and display a custom cursor and icon in the client area of ​​the window

HICON         hIcon = LoadIcon (hInstance, MAKEINTRESOURCE ( IDI_ICON1 ));

HCURSOR       hCursor = LoadCursor (hInstance, MAKEINTRESOURCE ( IDC_CURSOR1 ));

...

DrawIcon(hdc, 160, 80, hIcon);

DrawIcon(hdc, 100, 80, hCursor);

Handle the right mouse button, add shortcut menu processing

HMENU hSubMenu; // global variables

static BOOL InitWindow(HINSTANCE hInstance, int iCmdShow)

{

    ...

    HMENU hMenu = LoadMenu ( hInstance , MAKEINTRESOURCE ( IDR_MENU2 ));

    hSubMenu = GetSubMenu(hMenu, 1);

.....

}

LRESULT CALLBACK WinProc ( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

...

case WM_RBUTTONDOWN :        // mouse message

        GetCursorPos(&stPos); // Get the cursor position

        TrackPopupMenu(hSubMenu, TPM_LEFTALIGN , stPos.x, stPos.y, NULL , hWnd , NULL ); // Display the shortcut menu at the specified position

    return 0;

...

}

Guess you like

Origin blog.csdn.net/qq_22471349/article/details/131013607