Several techniques for Visual C programming
Visual C is an object-oriented visual programming tool that provides APPWizard automatically generates standard frameworks for applications, greatly alleviating programming workload. This article mainly introduces the following programming skills: Modify the main window style, create an irregular shape window, click the window title strip, use the context menu, so that the application can only run an instance, enable the application to display the task Icon and display rotation text in the notification area.
1. Modify the main window of the application framework generated by the main window style AppWizard with the default window style, such as automatically adding a document name in the window title strip, the window is superimposed, change the window size. To modify the default style of the window, you need to overload the CWnd :: PrecreateWindow function and modify the Createstruct type parameter CS. The CWnd :: PrecreateWindow function is executed before the window creates a function. If the function is overloaded, the window creation function will create a window to create a window style that the CreateStruct CS parameter returned by the CWnd :: PrecreateWindow function; otherwise use a predefined window style. The CreateStruct structure defines the initial parameters used by the creation function creation window, which is defined as follows: typedef struct tagcreatestruct {lpvoid lpcreateParams; // Create the basic parameter of the window Handle Hinstance; // With the module instance handle of the window that will be created, HMenu HMenu; The menu handle of the new window hwnd hwndparent; // The parent window of the new window; // New window The height INT CX; // New window width int y; // The upper left corner of the new window Y coordinate int x; / / New window The upper left corner X coordinate long style; // New window style lpcstr lpszname; // New window name lpcstr lpszclass; // New window window class name DWORD DWEXSTYLE; / / New window extension parameters} CreateStruct; The style domain of the CreateStruct structure defines the style of the window. For example, the default MDI main window includes fws_addtotitle (displayed in the title bar), fws_prefixtitle (put the document name in front of the program title), WS_THICKFRAME (window has a scalable border), etc. style. Since multiple style parameters are combined with logic or ("|"), add a style, just add the corresponding parameters to the style domain of the CreateStruct structure; delete the existing style, It is necessary to use the "&" to connect the style domain of the CreateStruct structure and the logical non-value of the style. The X, Y, CX, CY domains of the CreateStruct structure define the initial position and size of the window, and therefore, in the CWnd :: PrecreateWindow function, the value of the window will be able to define the initial display position and size of the window. The code in the following example will be fixed to 1/4 screen, and only the window name is displayed in the title strip, and the document name is not displayed. Bool CMAINFRAME :: PrecreateWindow (CreateStruct & Cs) {// Todo: Modify The window Class Or Styles Here by MODIFYING // The Createstruct CS
// Modify the main window style cs.style & = ~ fws_addtotitle; remove document name cs.style & = ~ ws_thickframe in the title bar; remove the border cs.style | = ws_dlgframe; increase the size of the size cannot be changed //// Determine the size and initial position of the main window INT cxscreen = :: getSystemMetrics (SM_CXSCREEN); // get the screen width int Cyscreen = :: getSystemMetrics; // Get the screen height cs.x = 0; // Main window is on the left Corner cs.y = 0; cs.cx = cxscreen / 2; // The main window is 1/2 screen width cs.cy = cxscreen / 2; // Main window high to 1/2 screen high return cmdiframewnd :: PrecreateWindow (cs);
2. Creating an irregular shape window The Windows window is rectangular, but at some time we need non-rectangular windows, such as circular, or even irregular. The Unregulated Shape Window can be created with the SETWINDOWRGN function of the CWND class. The function prototype of CWnd :: setWindowRGN is as follows: int setWindowRGN (HRGN HRGN, / / window area handle Bool BredRaw); // Whether the redo window CRGN classes encapsulate data and operations about the area. The HRGN value can be obtained from the CRGN class through (hRGN). CRGN provides CreateRectrGN, CreatellipticRGN, and CreatePolygonRGN member functions, which are used to create rectangles, (elliptical) and polygonal regions, respectively. The method of creating a non-rectangular window is as follows: First, the area class member data (such as CRGN M_RGNWND) is defined in the window class; secondly, call the CRGN class CreateRGN, CRETEELLIPTICRGN or CREATEPOLYGONRGN function created in the OnInitDialog function of the window. The area you need and call the SetWindowRGN function. The following example will generate an ellipse window. 1. Select the New command in the File menu in Developer Studio, select Create an MFC AppWizard (EXE) frame application in the New dialog box, and enter the project name Ellipsewnd. Setting the application type is based on a dialog (Dialog Based), and other options create project source files by default. 2. Use the resource editor from the main dialog (IDD_ellipseWnd_Dialog) to set all the controls from its property dialog (Dialog Properties) to POPUP, no title bar and border. 3. Add a CRGN class CellipseWndDLG to the main dialog class CellipseWndDLG in the EllipseWnddlg.h source file, which will define the area of the window. 4. Modify the OnInitDialog () function of the primary dialog class CellipseWnddlg in the EllipseWnddlg.cpp source file, increase the creation of m_rgnwnd, and define it as window area. The bold statement is a new part. BOOL CEllipseWndDlg :: OnInitDialog () {CDialog :: OnInitDialog (); // Add "About ..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT ((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT (IDM_ABOUTBOX <0xF000); CMenu * pSysMenu = GetSystemMenu (FALSE);! if (pSysMenu = NULL) {CString strAboutMenu; strAboutMenu.LoadString (IDS_ABOUTBOX); if (strAboutMenu.IsEmpty (!)) {pSysMenu-> Appendmenu (mf_separator); psysmenu-> appendmenu (mf_string, idm_aboutbox, straboutmenu);}}
// set the icon for this dialog. The framework does this automatic or //en the application's main window is not a dialogseticon (m_hicon, true); // set big iconseticon (m_hicon, false); // set small icon // setting The window title is "Elliptical Window", although the dialog box does not have a title bar, but still needs title SETWINDOWTEXT in the button's button (_t ("ellipse window"));
// Get the screen width, height, int cxScreen = :: GetSystemMetrics (SM_CXSCREEN); int cyScreen = :: GetSystemMetrics (SM_CYSCREEN); // set elliptical X, Y direction of the radius int nEllipseWidth = cxScreen / 8; int nEllipseHeight = cyScreen / 8 ;
// set the window size width nEllipseWidth, and moved to the top left corner of high nEllipseHeight // MoveWindow (0, 0, nEllipseWidth, nEllipseHeight); // Create an elliptical area m_rgnWndm_rgnWnd.CreateEllipticRgn (0, 0, nEllipseWidth, nEllipseHeight);
// Set m_rgnwnd as window area setWindowRGN ((hrgn) m_RGNWND, TRUE);
Return True; // Return True UnsS you set the focus to a control}
3. Click the window Title Bar with the mouse to move the Window Mobile Standard window to be implemented by clicking the window title strip with the mouse, but for the window without the title bar, you need to use the mouse to click the window title bar. window. There are two ways to achieve this goal. Method 1: When the window determines the mouse position, Windows sends a WM_NCHITTEST message to the window, so that as long as the mouse is in the window, Windows believes that the mouse is on the title bar. This requires the ONNCHITTEST function for the CWND class to handle the WM_NCHITTEST message. When you call the function of the parent class, if you return to HTClient, you will indicate that the mouse is in the window client area, return the overload function to htcaption, so that Windows mistakenly believes that the mouse is in the title bar on. The following example is the actual code to use this method: uint cellipsewnddlg :: Onnchittest (cpoint point) {// get the window area where the mouse is located uint nhittest (POINT);
// If the mouse is on the window customer area, then return the title submit to Windows // Make Windows to the title bar on the title bar, you can click the mobile window return (nhittest == htclient)? Htcaption: nhittest;} method 2: When the user presses the left mouse button in the window customer area, the Windows considers the mouse to be on the title bar, that is, sending a WPARAM parameter in the processing function on the WM_LBUTTONDOWN message, the WM_nclButtondown message for the current coordinate is sent to the current coordinate of the current coordinate. Below is the actual code using this method: void cellipsewnddlg :: ONLBUTTONDOWN (UINT NFLAGS, CPOINT) {// Call the parent class handler Complete basic operation CDialog :: ONLBUTTONDOWN (NFLAGS, POINT); // Send WM_NCLBUTTONDOWN message // Windows thinks the mouse on the title bar Postmessage (WM_NCLBUTTONDOWN, HTCAPTION, MAKELPAR (Point.x, Point.y));
4. Using the context menu Windows 95 application supports the function of the first-click menu, which can be implemented by handling the WM_CONTextMenu message. When you right click in the window, the window will receive the WM_CONTEXTMENU message, load the context menu within the process of the message, and call the CMenu :: TrackPopUpMenu function to display the context menu. The prototype of the CMenu :: TRACKPOPUPMENU function is as follows: BOOL TRACKPOPUPMENU (uint nflags, // Display and selection mode flag INT X, int y, // display menu left upper corner coordinate CWND * PWND, // Receive menu operation window object LPCRect LPRECT = NULL); // Sensitive area In order to use the context menu, first should prepare the context menu in the resource editor, assume the context menu name is IDR_MENU_CONText; secondly, use the classwizard to add a function on the message WM_CONTEXTMENU to the window ONCONTEXTMENU, and each menu command Processing function; then write the corresponding code. The following is the code instance of the onContextMenu function: void cellipsewnddlg :: OnContextMenu (CWND * PWND, CPOINT) {cmenu Menu
// Load menu menu.loadMenu (idR_Menu_Context);
// Display menu menu.getsubmenu (0) -> TRACKPOPUPMENU (TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RightButton, Point.x, Point.y, this);}
5. Make an application only run an instance of Windows is a multi-process operating system, the application generated by the framework can run multiple running instances. However, in some cases to ensure the safe operation of the application, the request can only run an instance, such as the program to use special hardware (such as modem) that can be used separately by one process, must restrict only one instance. Here, two basic problems are related to how to find that the program has an instance running in the second instance of the program, but how to activate the first instance, while the second instance exits. For the first problem, the amount of semaphore can first detect the amount of semaphore, if the example is presented, as already existing, then the program has run an instance. The second problem is to get the first instance of the main window object pointer or handle, and then set for setForeGroup to activate. Although the FindWindow function is looking for a routing window, the function requires the title or window class name of the lookup window, not a way to implement a general method. We can use Win 32 SDK function setprop to set a unique tag to the application host window. With GetDesktopWind, you can get a Windows system master window object pointer or handle. All application hosts can see the sub-window of the window, which is available to get their object pointers or handles with getWindow functions. Using Win 32 SDK Functions getprop lookups that each application main window contains the specific tags we set to determine if it is the first instance main window we have to find. Make the second instance very simple, just return the InitInstance function of its application object to false. In addition, when the main window exits, apply the RemoveProp function to delete the tag we set for it. The following initInstance, oncreate, and overdestroy function code will implement the above operations: BOOL CELLIPSEWNDAPP :: InitInstance () {// Create a selection of semaphore HSEM = CreateSemaphore (NULL, 1, 1, M_PSZEXENAME); // selection existed? // Signal amount exists, then the program has an instance running IF (getLastError () == Error_already_exists) {// Turn the Signal Signal Handle CloseHandle (HSEM);
// Looking for the main window of the previous instance hWnd hwndprevious = :: getWindow (: getDesktopWindow (), gw_child); while (: iswindow (hwndprevious)) {// Check the window whether there is a preset tag? // Have, then Is the main window IF (:: getprop (hwndprevious, m_pszeename)) {// main window to restore its size if (: isiconic (hwndput, sw_restore): showwindow (hwndprevious, sw_restore); // Activate the main window :: setForegroundWindow (HWndprevious); // Activate the dialog of the main window :: setForegroundWindow (: getLastactivePopup (HWndPrevious));
// Exit this example Return False;}
/ / Continue to find the next window hwndprevious = :: getWindow (hwndprevious, gw_hwndnext);
// The previous instance already exists, but it can't find its main window // may have an error // exit this instance Return False;}
AFXENABLECONTROLCONTAINER ();
// Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need # ifdef _AFXDLLEnable3dControls ();. / / Call thisime sale mfc in a Shared DLL # elseenable3dcontrolsstatic (); // call this when linking to mfc staticly # Endif
CEllipseWndDlg dlg; m_pMainWnd = & dlg; int nResponse = dlg.DoModal (); if (nResponse == IDOK) {// TODO: Place code here to handle when the dialog is // dismissed with OK} else if (nResponse == IDCANCEL ) {// Todo: Place Code Here to Handle by Dialog Is // DISMISsed with Cancel}
// Since the Dialog Has Been Closed, Return False So That We Exit The // Application, Rather Than Start The Application's Message Pump.Return False;
INT CELLIPSEWNDDLG :: OnCreate (lpcreatestruct lpcreatestruct) {if (cdialog :: oncreate (lpcreatestructure) == -1) Return -1;
/ / Settings Looking for Tags: SetProp (m_hwnd, AfxGetApp () -> M_PSZEXENAME, (HANDLE) 1);
Return 0;}
Void CellipseWnddlg :: ONDESTROY () {cdialog :: ONDESTROY ();
// Delete Look :: removeProp (m_hwnd, afxgetApp () -> m_pszeename);
6. Make the application to the icon in the task bar notification area There is a region in the right side of the Windows 95 task bar, which is called a notification area where some applications can be displayed. Click the icon with the mouse to be popped up. The application's menu, double-click, can display the full window interface of the application. Clock and volume control are the most common icons in the task bar notification area. The Task Standard Notification Area can be implemented by the Windows 95 shell programming interface function shell_notifyicon, which is declared in the shellapi.h header file, whose prototype is as follows: Winshellapi Bool WinAPI shell_notifyicon (dWMess PnID); dwMessage is the notification area icon The message is performed, there are three in three, as shown in the following table. SHELL_NOTIFYICON The Message Message Description NIM_ADD Insert an icon NIM_DELETE inserts an icon NIM_DELETE in the task bar notification area to delete an icon NIM_ Modify to modify the icon of the task bar notification area
PNID is incorporated into a pointer for a Notifyicondata structure. NOTIFYICONDATA structure declarations and various domains meaning the following: typedef struct _not _not otiicondata {// Nid DWORD CBSIZE; // NOTIFYICONDATA structure The number of bytes hWnd hWnd; // Processes the window handle of the notification area icon message; // Notification area icon Iduint uflags; // indicates whether the following three identification markers uint ucallbackMessage; // mouse click the IDHICON HICON; // icon handle char sztip [64]; // When the mouse is moved to the icon Show prompt information} NOTIFYICONDATA, * PNOTIFYICONDATA; when using shell_notifyicon placed an icon in the task note notification area, a callback message is also defined, and when the user clicks or double-click the icon, the window handle specified in the Notifyicondata structure This message will be accepted. The LPARAM parameter of this message will illustrate the mode of the mouse operation. When the application exits, you should delete the icon in the task bar. The following example will explain how to display the aforementioned ellipse window program as an icon in the task bar notification area, and when the mouse click the icon, a menu will pop up, when double-click, the ellipse window will completely display. 1. Add a menu item in the IdR_Menu_Context menu of the EllipseWnd project (IDM_INSERTICON) in the Task Bar with the Resource Editor. 2. Add a menu resource IDR_MENU_ICON in the EllipseWnd project, set three menu items in it: "Activate the Ellipse Window" (IDM_ActiveWindow) "About ..." (IDM_AboutBox) "Exit ALT F4 "(ID is IDM_EXIT) 3. Define a message UM_ICONNNOTIFY in the CellipseWnddlg.h source file to respond to the icon operation and add the processing function on the response message in the CellipseWndDLG class definition. Use ClassWizard to add the function definition and template of the response menu command IDM_INSERTICON and IDM_ACTIVEWINDOW. The modifications in CellipseWnddlg.h are as follows:
// Define the message of the response icon operation #define um_iconnotify wm_user 100
Class CellipseWnddlg: Public CDialog {// ConstructionPublic: CellipseWnddlg (CWND * PParent = NULL); // Standard Constructionor
// Dialog DataFile: // {{AFX_DATA (CellipseWnddlg) ENUM {IDD = IDD_ELLIPSEWND_DIALOG}; // Note: The classwizard will add data members Herefile: //}} AFX_DATA
// ClassWizard generated virtual function overridesfile: // {{AFX_VIRTUAL (CEllipseWndDlg) protected: virtual void DoDataExchange (CDataExchange * pDX); // DDX / DDV supportfile: //}} AFX_VIRTUAL
// ImplementationProtace: hicon m_hicon; crgn m_rgnwnd;
/ / Handling the function function of the icon Description Bool Addicon (); Bool deleteicon ();
// Generated message map functionsfile: // {{AFX_MSG (CEllipseWndDlg) virtual BOOL OnInitDialog (); afx_msg void OnSysCommand (UINT nID, LPARAM lParam); afx_msg void OnPaint (); afx_msg HCURSOR OnQueryDragIcon (); afx_msg void OnLButtonDown (UINT nFlags , CPoint point); afx_msg void OnContextMenu (CWnd * pWnd, CPoint point); afx_msg void OnAboutbox (); afx_msg void OnExit (); afx_msg int OnCreate (lPCREATESTRUCT lpCreateStruct); afx_msg void OnDestroy (); afx_msg void OnInserticon (); afx_msg void OnActivewindow (); file: //}} message handler aFX_MSG // icon Description afx_msg void OnIconNotify (WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP ()}; 4 mapping entry in the add message CEllipseWndDlg.cpp follows:. BEGIN_MESSAGE_MAP (CEllipseWndDlg, CDialog) file: // {{AFX_MSG_MAP (CEllipseWndDlg) ON_WM_SYSCOMMAND () ON_WM_PAINT () ON_WM_QUERYDRAGICON () ON_WM_LBUTTONDOWN () ON_WM_CONTEXTMENU () ON_COMMAND (IDM_ABOUTBOX, OnAboutbox) ON_COMMAND (IDM_EXIT, OnExit) ON_WM_CREATE () ON_WM_DESTROY () ON_COMMAND ( IDM_INSERTICON, OnSERTICON) ON_COMMAND (IDM_ACTIVEWINDOW, OnActiveWindow) File: //}} AFX_MSG_MAP ON_MESSAGE (UM_ICONNNOTIFY, ONICONNNOTIFY) end_MESSAGE_MAP ()
5. Add the following functions or code in CellipseWnddlg.cpp: Void CellipseWnddlg :: ONDESTROY () {cdialog :: ONDESTROY ();
// remove main window tag :: removeprop (m_hwnd, afxgetApp () -> m_pszeename;
// When the application exits, delete the icon deleteicon ();};
BOOL CEllipseWndDlg :: AddIcon () {// increase in the task bar icon NOTIFYICONDATA nid; nid.cbSize = sizeof (nid); nid.hWnd = m_hWnd; nid.uID = IDR_MAINFRAME; nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; Nid.ucallbackMessage = um_iconnotify; nid.hicon = m_hicon; cstring str = "Elliptic window"; lstrcpyn (Nid.sztip, (lpcstr) str, sizeof (nid.sztip) / sizeof (nid.sztip [0]);
Return shell_notifyicon (nim_add, & nid);
BOOL CEllipseWndDlg :: DeleteIcon () {// delete icon NOTIFYICONDATA nid Taskbar; nid.cbSize = sizeof (nid); nid.hWnd = m_hWnd; nid.uID = IDR_MAINFRAME; return Shell_NotifyIcon (NIM_DELETE, & nid);}
// Response Icon Message Processing Void CellipseWnddlg :: OnCIPSewnddlg :: OnConnotify (WPARAM WPARAM, LPARAM LPARAM) {Switch ((UINT) LPARAM) {// Mouse Click Operation Case WM_LButtondown: Case WM_RBUTTONDOWN: {// Load Icon Action Menu CMenu Menu Menu.LoadMenu (idR_Menu_icon);
// Mouse Click Cpoint Point; getCursorpos (& POINT);
// activate the background window to setForegroundWindow ();
// Display Icon Menu Menu.getsubmenu (0) -> TRACKPOPUPMENU (TPM_LEFTBUTTON | TPM_RightButton, Point.x, Point.y, this, null);
// Add an additional message to make the menu to operate correct PostMessage (WM_USER, 0, 0); Break;} // Mouse Double-click Operation Case WM_LBUTTONDBLCLK: // Activate the application onactiveWindow (); Break;}}
// Insert the icon to the task bar Notification Void CellipseWndDlg :: OnSilticon () {// First hide the main window ShowWindow (SW_HIDE); // Insert icon Addicon ();
// Activate the main window void CellipseWnddlg :: onactiveWindow () {// First remove the icon deleteicon (); // Display the main window ShowWindow; UpdateWindow ();}
7. Show the rotating text in applications, in order to achieve a special effect, you often need to display the rotated text. The text display mode, including rotation, is set by the font. The properties of the font are mainly used by the LogFont structure used by the font, which specifies the angle of the text line and the X-axis (horizontal axis) in this structure. The angle unit is very. In order to be all fonts to rotate in the same direction, the LFCLIPPRECISION field of the LogFont structure should also be set to Clip_LH_ANGLES. The following code will appear in the dialog box to display a line of lines every 15 degrees: void crotatetextdlg :: onpaint () {cpaintdc dc (this); // device context for Painting
IF (isiconic ()) {sendMessage (WM_ICONERASEBKGND, (WPARAM) dc.getsafehdc (), 0);
// Center icon in client rectangleint cxIcon = GetSystemMetrics (SM_CXICON); int cyIcon = GetSystemMetrics (SM_CYICON); CRect rect; GetClientRect (& rect); int x = (rect.Width () - cxIcon 1) / 2; int y = (RECT.HEIGHT () - CYICON 1) / 2;
// Draw the icondc.drawicon (x, y, m_hicon);} else {crect rc; getClientRect (RC);
CSTRING STR (_t (".......... rotate text!")); Dc.setbkmode (transparent); Dc.SetTextColor (RGB (0, 0, 255));
CFONT FONT; LOGFONT LF; MEMSET (& LF, 0, SIZEOF (Logfont));
Lf.lfheight = -14; lf.lfweight = fw_normal; lf.lfclipprecision = clip_lh_angles; strcpy (lf.lffacename, "Song");
For (int i = 0; i <3600; i = 150) {lf.lfescapement = i;
Font.createFontIndirect (& lf); cfont * PoldFont = dc.selectObject (& font);
Dc.TextOut (rc.right / 2, rc.bottom / 2, str);
Dc.selectObject (PoldFont); font.deleteObject ();
CDIALOG :: onpaint ();}}