A Windows control that is positioned on a host uses a rectangular confinement known as its bounding rectangle. To assist you with knowing what that rectangular area is, the CWnd class is equipped with a method named GetWindowRect. Its syntax is: void GetWindowRect(LPRECT lpRect) const; When calling this method, pass a RECT or or a CRect variable by reference. When this function exits, it returns the argument that was passed: CRect Recto; m_Panel.GetWindowRect(&Recto);
As mentioned already, the origin of the screen is positioned on the top-left corner of the monitor. This is referred to as, or is said that the location uses, screen coordinates. The origin of a client area is placed on its top-left corner. This is referred to as, or is said that the location uses, client coordinates. For example, the origin used by the above GetWindowRect() method is based on the screen. If you want the rectangle resulting from a call to either the GetClientRect() or the GetWindowRect() methods to be based on the client area (on client coordinates) of the control that called it, you can transfer the origin from the screen to the client. This is conveniently done with a call to the CWnd::ClientToScreen() method. It is overloaded as follows: void ClientToScreen(LPPOINT lpPoint) const; void ClientToScreen(LPRECT lpRect) const; If the location you had requested is a point, pass its POINT or its CPoint variable to the ClientToScreen() method. If the value you requested is a rectangle, pass its RECT or its CRect variable. Here is an example: CRect Recto; m_Panel.GetWindowRect(&Recto); . . . Some Code ScreenToClient(Recto); dc.Rectangle(Recto); This time, even if the dialog box moves, the
GetWindowRect() method returns the same rectangle. void ScreenToClient(LPPOINT lpPoint) const; void ScreenToClient(LPRECT lpRect) const; This method follows the opposite logic of the ClientToScreen() method.
For you the programmer, the control identifier may be one of the most important properties of a window. For the user, this is not the case. For a text-based control, the most important part, as far as the user is concerned, may be its text. Many controls use text. In fact, one of the most obvious items on most windows such as dialog boxes is the text they display. This text allows the user to identify a window. We saw that some of the controls that use text would allow you to change the Caption property at design time. On the other hand, while a using is interacting with your application, depending on various circumstances, at a certain time you may want to change the text that a Windows control is displaying or holding. To assist you with this, the CWnd class is equipped with a method named SetWindowText. Its syntax is: void SetWindowText(LPCTSTR lpszString); The lpszString argument is a null-terminated string that holds the value you want to display. It can be configured using any of the valid null-terminated string operations. Here is an example that changes the title of a dialog box when the window displays. The text is provided as a null-terminated string passed to the method: BOOL CDismissDlg::OnInitDialog() { CDialog::OnInitDialog(); SetWindowText("Windows Fundamentals"); return TRUE; } Another technique you can use consists of first
declaring a null-terminated string variable, assigning it a value, and then
passing it as the lpszString argument to the SetWindowText()
function. CString Str; Str.LoadString(IDS_CURAPPNAME); SetWindowText(Str); To change the name of a window, instead of calling SetWindowText(), you can call the CWnd::SendMessage() method. Since you want to change the text, the message argument must be WM_SETTEXT. The wParam argument is not used. The lParam argument holds the string that will be the new value of the window name. You must cast the string to LPARAM. Here is an example that allows the user to click a menu item that changes the title of the frame window: char NewTitle[] = "Introduction to Windows Programming"; SendMessage(WM_SETTEXT, NULL, reinterpret_cast<LPARAM>(NewTitle)); To retrieve the name of a window (always remember that the name of a window is not the name of a class) or the text stored in a control, you can call the CWnd::GetWindowText() function. Its syntax is: int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const; The lpszStringBuf is the null-terminated string that will store the window name. The nMaxCount is the minimum number of characters of the lpszStringBuf. If you specify more characters than the name is made of, the compiler would reduce this number to the actual length of the string. Therefore, it is safe to provide a high number.
We saw how to manually specify a control's location and size during design:
Once a window or a control has been positioned on the screen or in its confined client area, it keeps these attributes until specified otherwise. When dealing with a main window, such as dialog box, the user can move it around the screen as necessary and if possible. This is usually done by dragging the title bar. When the user grabs the title bar of a dialog box and starts dragging to move it, the window sends the WM_MOVING message. The WM_MOVING event fires the OnMoving() event. This event is usually left alone as it allows the user to use an application as regularly as possible. The syntax of the OnMoving() event is: afx_msg void OnMoving(UINT nSide, LPRECT lpRect); The OnMoving() event fires while the window is being moved. The nSide argument specifies the side of window that is moving. As the window is moving, this event returns its location and size as the values of the lpRect member variables. If you create a certain type of window and you do not want the user to move it around, you can write code for the WM_MOVING message. In the following example, the user cannot move the window as its location and dimensions are restored with a #define WS_TABSTOP 0x00010000L. Here is an example that prevents the user from moving a dialog box: void CExerciseDlg::OnMoving(UINT fwSide, LPRECT pRect) { CDialog::OnMoving(fwSide, pRect); // TODO: Add your message handler code here CRect CurRect; // Find out the location and the dimensions of the window GetWindowRect(&CurRect); // You ain't moving nothin' pRect->left = CurRect.left; pRect->top = CurRect.top; pRect->right = CurRect.right; pRect->bottom = CurRect.bottom; } To programmatically move a window, call the CWnd::SetWindowPos() method. Its syntax is: BOOL SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags); The pWndInsertAfter argument is used to specify the window that will positioned in the Z coordinate on top of the window that called this method. If you have the class name or the CWnd name of the other window, pass it as the pWndInsertAfter argument. Otherwise, this argument can have one of the following values:
If you are not trying to reposition the window in the Z coordinate, pass this argument as NULL or include the SWP_NOZORDER value for the nFlags argument. The nFlags argument is used to define how the location arguments (x and y) and the dimensions (cx and cy) will be dealt with. These other arguments have the following roles:
Additionally, the nFlags argument can have one of the following values or one of the above nFlags values can be combined with the following values:
void CTestDialog::OnBtnMovePanel() { m_Panel.SetWindowPos(NULL, 40, 72, 100, 86, SWP_NOZORDER); } If you specify negative values for the left and top distances, either the left or the top borders, respectively, will be hidden.
After a control has been created, if you need to perform some type of drawing such as changing its color, you can use the WM_CTLCOLOR message which fires the OnCtlColor() event
Text-based controls (the controls that display text) align their text to the left by default. This means that when the control displays, its text starts on the left side of its area (for US English and other Latin-based versions of Microsoft Windows). To align text to the left on a control that allows it, at design time, select the Left value in the Align Text combo box
A control is said to have focus if it is ready to receive input from the user. For example, if a text-based control has focus and the user presses a character key, the corresponding character would be displayed in the control. Controls show different ways of having focus. For example, when a text box has focus, a caret is blinking in it. When a button has focus, it displays a thick border or a dotted rectangle around its caption:
There are two main ways a control receives focus: based on a user's action or an explicit request from you. To give focus to a control, the user usually presses Tab, which allows navigating from one control to another. To allow you to programmatically give focus to a control, the CWnd class is equipped with a method named SetFocus. Its syntax is: CWnd* SetFocus( ); This method gives focus to the control that called it. In the following example, an edit box identified as IDC_EDIT1 will receive focus when the user clicks the button: CButton *btnFirst; btnFirst = (CButton *)GetDlgItem(IDC_EDIT1); btnFirst->SetFocus(); Once a control receives focus, it initiates a WM_SETFOCUS message, which fires an OnSetFocus() event. The syntax of the CWnd::OnSetFocus() event is: afx_msg void OnSetFocus(CWnd* pOldWnd); You can use this event to take action when, or just before, the control receives focus. At anytime, to find out what control has focus, call the CWnd::GetFocus() method. Its syntax is: static CWnd* PASCAL GetFocus(); This method returns a handle to the control that has focus at the time the method is called. While the user is interacting with your application, the focus changes constantly. For this reason, you should avoid using the return type of this method from various events or member functions. In other words, do not globally declare a CWnd variable or pointer, find out what control has focus in an event Event1 and use the returned value in another event Event2 because, by the time you get to Event2, the control that had focus in Event1 may have lost focus. In fact, the dialog box that holds the control or the main application may have lost focus. Therefore, use the GetFocus() method only locally.
After a control has been created, for the user to take advantage of it, it must be made visible. When it comes to their visibility, there are two types of windows: those the user can see and interact with, and those invisible controls that work only behind the scenes and cannot be displayed to the user. During control design, a window can be displayed to the user by setting its Visible property to True in the Properties window or by adding it the WS_VISIBLE style. If you did not set the Visible property to True or did not add the WS_VISIBLE style, the control would be hidden (but possibly available). To help you display a hidden control, the CWnd class is equipped with a method named ShowWindow. Its syntax is: BOOL ShowWindow(int nCmdShow); This method is used to display or hide any window that is a descendent of CWnd. Its argument, nCmdShow, specifies what to do with the appearance or disappearance of the object. Its possible values are:
To use one of these constants, pass it to the ShowWindow() method. For example, to minimize a window that is minimizable, you would use code as follows: ShowWindow(SW_SHOWMINIMIZED); Remember that this method is used to either hide or to display a control by passing the appropriate constant, SW_HIDE to hide and SW_SHOW to display it. Here is an example that displays a control that missed the WS_VISIBLE property when it was created: void CSecondDlg::OnFirstControl() { CWnd *First = new CWnd; CString StrClsName = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, LoadCursor(NULL, IDC_CROSS), (HBRUSH)GetStockObject(BLACK_BRUSH), LoadIcon(NULL, IDI_WARNING)); First->Create(StrClsName, NULL, WS_CHILD); First->ShowWindow(SW_SHOW); } When the ShowWindow() method is called with the SW_SHOW value, if the control was hidden, it would become visible; if the control was already visible, nothing would happen. In the same way, when this method is called with the SW_HIDE argument, the control would be hidden, whether it was already hidden or not. To help you check the visibility of a control before calling the ShowWindow() method, the CWnd class is equipped with a method named IsWindowVisible. Its syntax is: BOOL IsWindowVisible() const; This method returns TRUE if the control that called it is already visible. If the control is hidden, the method returns FALSE.
We saw that when a control has been created, it is available to the user who can interact with its value. This is because a control usually has its Disable property set to False in the Properties window. A control is referred to as disabled if the user can see it but cannot change its value. If for any reason a control is disabled, to let you enable it, the CWnd class is equipped with the EnableWindow() method. In fact, the EnableWindow() method is used either to enable or to disable a window. Its syntax is: BOOL EnableWindow(BOOL bEnable = TRUE); Here is an example that disables a control called Memo: void CSecondDlg::OnDisableMemo() { memo->EnableWindow(FALSE); } When calling the EnableWindow() method, if you pass the FALSE value, the control is disabled, whether it was already disabled or not. If you pass the TRUE constant, it gets enabled even it was already enabled. Sometimes you may want to check first whether the control is already enabled or disabled. To help you with this, CWnd class provides the IsWindowEnabled() method. Its syntax is: BOOL IsWindowEnabled( ) const; This method checks the control that called it. If the control is enabled, the member function returns TRUE. If the control is disabled, this method returns FALSE. Here is an example: void CSecondDlg::OnDisableMemo() { if( memo->IsWindowEnabled() == TRUE ) memo->EnableWindow(FALSE); else // if( !memo->IsWindowEnabled() ) memo->EnableWindow(); } Here is a simplified version of the above code: void CSecondDlg::OnDisableMemo() { memo->EnableWindow(!Memo->IsWindowEnabled()); } |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|