CWnd::OnSysCommand()
afx_msg void onSysCommand(UINT nID, LPARAM lParam);
Parameters
nID
Specifies the type of system command requested. This parameter can be any one of the following values:
SC_CLOSE Close the CWnd object.
SC_HOTKEY Activate the CWnd object associated with the application-specified hot key. The low-order word of lParam identifies the HWND of the window to activate.
SC_HSCROLL Scroll horizontally.
SC_KEYMENU Retrieve a menu through a keystroke.
SC_MINIMIZE (or SC_ICON) Minimize the CWnd object.
SC_MAXIMIZE (or SC_ZOOM) Maximize the CWnd object.
SC_MOUSEMENU Retrieve a menu through a mouse click.
SC_MOVE Move the CWnd object.
SC_NEXTWINDOW Move to the next window.
SC_PREVWINDOW Move to the previous window.
SC_RESTORE Restore window to normal position and size.
SC_SCREENSAVE Executes the screen-saver application specified in the [boot] section of the SYSTEM.INI file.
SC_SIZE Size the CWnd object.
SC_TASKLIST Execute or activate the Windows Task Manager application.
SC_VSCROLL Scroll vertically.
lParam
If a control-menu command is chosen with the mouse, lParam contains the cursor coordinates. The low-order word contains the x coordinate, and the high-order word contains the y coordinates. Otherwise this parameter is not used.
- SC_HOTKEY Activate the window associated with the application-specified hot key. The low-order word of lParam identifies the window to activate.
- SC_SCREENSAVE Execute the screen-save application specified in the Desktop section of Control Panel.
Remarks
The framework calls this member function when the user selects a command from the control menu, or when the user selects the maximize or the minimize button.
(中文翻译:OnSysCommand()用于处理系统已定义的一些Command,譬如最小化,最大化和其他定义在Control Menu上一些命令ITEM)
我认为的Control menu就是当App最小化在TarkBar上的时候,点右键会由一个菜单显示出来,那个就是Control Menu。
知道正确答案的请举手!!!!!
By default, OnSysCommand carries out the Control-menu request for the predefined actions specified in the preceding table.
In WM_ONSYSCOMMAND messages, the four low-order bits of the nID parameter are used internally by windows. When an application tests the value of nID, it must combine the value oxFFF0 with the nID value by using the bitwise-AND operator to obtain the correct result.
The menu items in a control-menu can be modified with the GetSystemMenu, AppendMenu, InsertMenu, and ModifyMenu member functions. Applications that modify the Control menu must process WM_SYSCOMMAND messages, and any WM_SYSCOMMAND messages not handled by the application must be passed on to OnSysCommand. Any command values added by application must be processed by the application and cannot be passed to OnSysCommand.
An application can carry out any system command at any time by passing a WM_SYSCOMMAND message to OnSysComand.
(中文翻译:如果要是的Windows处理流程跳转到OnSysCommand(),那么我们可以自己发送WM_SYSCOMMAND message)
Accelerator (shortcut) keystrokes that are defined to select items from the Control menu are translated into OnSysCommand calls; all other accelerator keystrokes are translated into WM_COMMAND messages.
(中文翻译:所有的定义在ControlMenu中的快捷键组合,会发送消息,消息会被传输到OnSysCommand()响应处理;
其他的快捷键则会发送WM_COMMAND消息.)
这个时候响应函数需要自己定义。
在.cpp文件中定义:
BEGIN_MESSAGE_MAP(CVideoWindow, CWnd)
ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
ON_WM_MOUSEMOVE()
ON_WM_MOVE()
ON_COMMAND(MessageName,OnMessageName);// 自己定义的;END_MESSAGE_MAP()
在.h文件中定义:
public:
afx_msg LRESULT OnGraphNotify(WPARAM inWParam, LPARAM inLParam);
afx_msg LRESULT OnMessageName(WPARAM inWParam, LPARAM inLParam);// 参数可要可不要
......Note: This member function is called by the framework to allow your application to handle a windows message, the parameters passed to your function reflect the parameter received by the framework when the message was received. If you can call the base-class implementation of this function, that implementation will use the parameter originally passed with the message and not parameter you supply to the function.
WM_SYSCOMMAND ( in win32)
A window receive this message when the user choose a command from the window menu (formerly known as the system or control menu) or when user chooses the maximize button, minimize button, restore button or close button.
A window receives this message through its WindowProc function.
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_SYSCOMMAND
WPARAM wParam, // system command type
LPARAM lParam // horizontal and vertical position
);
Parameters
wParam
Specifies the type of the system command requested. This parameter can be one of the following values.
just to list the difference from the OnSysCommand(....) function's nID parameters.
value meaning SC_CONTEXTHELP Changes the cursor to a question mark with a pointer. If the user then clicks a control in the dialog box, the control receives a WM_HELP message. SC_DEFAULT Selects the default item; the user double-clicked the window menu. SC_MONITORPOWER Sets the state of the display. This command supports devices that have power-saving features, such as a battery-powered personal computer.
The lParam parameter can have the following values:
1 - the display is going to low power
2 - the display is being shut off
lParam
The low-order word specifies the horizontal position of the cursor, in screen coordinates, if a window menu command is chosen with the mouse. Otherwise, this parameter is not used.
The high-order word specifies the vertical position of the cursor, in screen coordinates, if a window menu command is chosen with the mouse. This parameter is –1 if the command is chosen using a system accelerator, or zero if using a mnemonic.
Return Values
An application should return zero if it processes this message.
Remarks
To obtain the position coordinates in screen coordinates, use the following code:
xPos = GET_X_LPARAM(lParam); // horizontal position yPos = GET_Y_LPARAM(lParam); // vertical positionThe DefWindowProc function carries out the window menu request for the predefined actions specified in the previous table.
In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.
The menu items in a window menu can be modified by using the GetSystemMenu, AppendMenu, InsertMenu, ModifyMenu, InsertMenuItem, and SetMenuItem functions. Applications that modify the window menu must process WM_SYSCOMMAND messages.
An application can carry out any system command at any time by passing a WM_SYSCOMMAND message to DefWindowProc. Any WM_SYSCOMMAND messages not handled by the application must be passed to DefWindowProc. Any command values added by an application must be processed by the application and cannot be passed to DefWindowProc.
Accelerator keys that are defined to choose items from the window menu are translated into WM_SYSCOMMAND messages; all other accelerator keystrokes are translated into WM_COMMAND messages.
If the wParam is SC_KEYMENU, lParam contains the character code of the key that is used with the ALT key to display the popup menu. For example, pressing ALT+F to display the File popup will cause a WM_SYSCOMMAND with wParam equal to SC_KEYMENU and lParam equal to 'f'.
BOOL IsZoomed( ) const;
Return Value
Nonzero if CWnd is maximized; otherwise 0. (从名字很容易误解是判断窗口是否缩放,实际来判断窗口是否处于最大化状态。非0表示窗口已最大化,否则窗口不呈最大化状态.)
Remarks
Determines whether CWnd has been maximized.
BOOL IsIconic( ) const;
Return Value
Nonzero if CWnd is minimized; otherwise 0.(判断窗口是否最小化状态)
Remarks
Specifies whether CWnd is minimized (iconic).
Example
// This code, normally emitted by the AppWizard for a dialog-based // project for the dialog's WM_PAINT handler, runs only if the // window is iconic. The window erase the icon's area, then // paints the icon referenced by m_hIcon. if (IsIconic()) { CPaintDC dc(this); // device context for painting IconEraseBkgnd(dc); // Center icon in client rectangle int 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 icon dc.DrawIcon(x, y, m_hIcon); }
GetWindowLong
The GetWindowLong function retrieves information about the specified window. The function also retrieves the 32-bit(long) value at the specified offset into the extra window memory.
If you are retrieving a pointer or a handle, this function has been superseded by the GetWindowLongPtr function.
Parameters
hWnd
[in] Handle to the window and, indirectly, the class to which the window belongs.
nIndex
[in] Specifies the zero-based offset to the value to be retrieved. Valid values are in the range zero through the number of bytes of extra window memory, minus four; for example, if you specified 12 or more bytes of extra memory, a value of 8 would be an index to the third 32-bit integer. To retrieve any other value, specify one of the following values.
value action GWL_EXSTYLE Retrieves the extended window styles. For more information, see CreateWindowEx. GWL_STYLE Retrieves the window styles. GWL_WNDPROC Retrieves the address of the window procedure, or a handle representing the address of the window procedure. You must use the CallWindowProc function to call the window procedure. GWL_HINSTANCE Retrieves a handle to the application instance. GWL_HWNDPARENT Retrieves a handle to the parent window, if any. GWL_ID Retrieves the identifier of the window. GWL_USERDATA Retrieves the user data associated with the window. This data is intended for use by the application that created the window. Its value is initially zero. The following values are also available when the hWnd parameter identifies a dialog box.
value action DWL_DLGPROC Retrieves the address of the dialog box procedure, or a handle representing the address of the dialog box procedure. You must use the CallWindowProc function to call the dialog box procedure. DWL_MSGRESULT Retrieves the return value of a message processed in the dialog box procedure. DWL_USER Retrieves extra information private to the application, such as handles or pointers.
Return Values
If the function succeeds, the return value is the requested 32-bit value.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
If SetWindowLong has not been called previously, GetWindowLong returns zero for values in the extra window or class memory.
The SetWindowLong function changes an attribute of the specified window. The function also sets the 32-bit (long) value at the specified offset into the extra window memory.
Note This function has been superseded by the SetWindowLongPtr function. To write code that is compatible with both 32-bit and 64-bit versions of Windows, use SetWindowLongPtr.
LONG SetWindowLong( HWND hWnd, // handle to window int nIndex, // offset of value to set LONG dwNewLong // new value );
Parameters
hWnd
[in] Handle to the window and, indirectly, the class to which the window belongs.
Windows 95/98/Me: The SetWindowLong function may fail if the window specified by the hWnd parameter does not belong to the same process as the calling thread.
nIndex
[in] Specifies the zero-based offset to the value to be set. Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer.
dwNewLong
[in] Specifies the replacement value.
Return Values
If the function succeeds, the return value is the previous value of the specified 32-bit integer.
If the function fails, the return value is zero. To get the extended error information, call GetLastError.
If the previous value of the specified 32-bit integer is zero, and the function succeeds, the return value is zero. but the function does not clear the last error information. This makes it difficult to determines success or failure. To deal with this, you should clear the last error information by calling SetLastError(0) before calling SetWindowLong. Then, function failure will be indicated by a return value of zero and a GetLastError result is nonzero.
Remarks
Certain window data is cached, so changes you make using SetWindowLong will not take effect until call the SetWindowPos function. Specifically, if you change any of the frame styles, you must call SetWindowPos with the SWP_FRAMECHANGED flag for the cache to be updated properly.
If you use SetWindowLong with the GWL_WNDPROC index to replace the window procedure, the window procedure must conform to the guidelines specified in the description of the WindowProc callback function.
.....
You must not call SetWindowLong with the GWL_HWNDPARENT index to change the parent of a child window. Instead, use the SetParent function.
If the window has a class style of CS_CLASSDC or CS_OWNDC, do not set the extended window styles WS_EX_COMPOSITED or WS_EX_LAYERED.
/* 用法 */
==========================================================
DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
dwStyle = dwStyle | WS_CAPTION | WS_THICKFRAME;
::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);==========================================================
BOOL ModifyStyle( DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0 );
Return Value
Nonzero if style was successfully modified; otherwise, 0.
Parameters
dwRemove
Specifies window styles to be removed during style modification.
dwAdd
Specifies window styles to be added during style modification.
nFlags
Flags to be passed to SetWindowPos, or zero if SetWindowPos should not be called. The default is zero. See the Remarks section for a list of preset flags.
Remarks
Call this member function to modify a window’s style. Styles to be added or removed can be combined by using the bitwise OR (|) operator. See the topics General Window Styles and ::CreateWindow in the Win32 SDK Programmer’s Reference for information about the available window styles.
If nFlags is nonzero, ModifyStyle calls the Windows API function ::SetWindowPos and redraws the window by combining nFlags with the following four preset flags:
SWP_NOSIZE Retains the current size.
SWP_NOMOVE Retains the current position.
SWP_NOZORDER Retains the current Z order.
SWP_NOACTIVATE Does not activate the window.To modify a window’s extended styles, see ModifyStyleEx.
Example
// This example adds the WS_CLIPCHILDREN style to the window. // No Styles are removed from the window. void CMyView::OnInitialUpdate() { CView::OnInitialUpdate(); ModifyStyle(0, WS_CLIPCHILDREN); }
窗口全屏解决方案
方案一:之前公司老旧的代码中有这样的方案。重载OnSysCommand()函数,让所有最大化操作变成自己定义的全屏操作,
然后在OnSysCommand中处理这样的全屏操作。改写系统默认的SW_MAXIMIZE处理方式。
要隐藏掉Dialog的Title和Border。在视频播放中这种全屏操作比较常见。
.cpp中
// 双击窗口部分,窗口最大化/或者向下还原
void CMainFrame::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SendMessage(WM_SYSCOMMAND, IsZoomed() ? SC_RESTORE : SC_MAXIMIZE, 0);
// CFrameWnd::OnLButtonDblClk(nFlags, point);
}
// 点击窗口Title bar上右方的最大化按钮/恢复按钮
void CMainFrame::OnRestore()
{
// TODO: Add your command handler code here
SendMessage(WM_SYSCOMMAND, IsZoomed() ? SC_RESTORE : SC_MAXIMIZE, 0);
}
///
// 重载OnSysCommand函数
// 自定义处理一些Systems Command
void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
static CRect rectPrevWindow;
if(nID == MAXIMIZE)
{// 保留窗口最大化之前的尺寸
GetWindowRect(&rectPrevWindow);
ModifyStyle(WS_CAPTION | WS_THICKFRAME, 0);CRect rectone(0,0,0,0);
CWnd *pwnd = GetDesktopWindow();
::GetWindowRect(pwnd->m_hWnd,rectone);
MoveWindow(rectone.left, rectone.top, rectone.Width(), rectone.Height());
}
eise if (nID == SW_RESTORE)
{
DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);dwStyle = dwStyle | WS_CAPTION | WS_THICKFRAME;
::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);
Invalidate(FALSE);// 还原窗口的大小
MoveWindow(rectPrevWindow.left, rectPrevWindow.top, rectPrevWindow.Width(), rectPrevWindow.Height());
}if(.....)// 处理其他的System Command操作;
}
方案二:点击某个Button进入全屏状态,那么不会修改掉系统默认的最大化操作。
CVideoCtlBar为控制条(Dialog), 它浮动在视频播放窗口(CVPlayer)上。
CVideoCtlBar.h中Button的响应函数声明
public:
afx_msg void OnButtonFullScreen(UINT nFlags, CPoint point);
CVideoCtlBar.cpp中响应函数实现:
在消息映射那里还有一部分声明。classwizard一般会自动生成。
BEGIN_MESSAGE_MAP(CVideoCtlBar, CDialog)
ON_WM_DESTROY()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_SIZE()
ON_WM_RBUTTONDOWN()
ON_BN_CLICKED(IDC_BUTTON_PMIN, &CVideoCtlBar::OnBnClickedButtonPmin)
ON_BN_CLICKED(IDC_BUTTON_PMAX, &CVideoCtlBar::OnButtonFullScreen)
END_MESSAGE_MAP()
void CVideoCtlBar::OnButtonFullScreen()
{
IsFullScreen = !IsFullScreen;
if(IsFullScreen)
{
((CVPlayer*)GetParent())->SetFullScreen(TRUE);
}
else
{
((CVPlayer*)GetParent())->SetFullScreen(FALSE);
}
}
CVPlayer为播放窗口;定义了设置视频窗口全屏的实现函数。
BOOL CVPlayer::SetFullScreen(BOOL inEnabled)
{
//return mGraph->SetFullScreen(inEnabled);// Directshow 模式下的FullScreen方式
// 采用另外一种方式全屏;计算窗口大小,得到显示器屏幕大小,进行缩放就可以;
static CRect rectPrevWindow;
mFullScreen = inEnabled;
if(inEnabled)
{
ModifyStyle(WS_CAPTION | WS_THICKFRAME, 0);
GetWindowRect(&rectPrevWindow); // 保存最大化之前的窗口大小
// 得到桌面Screen大小
CRect rectone(0,0,0,0);
CWnd *pwnd = GetDesktopWindow();
::GetWindowRect(pwnd->m_hWnd,rectone);
// 使得播放窗口变的覆盖整个Screen
MoveWindow(rectone.left, rectone.top, rectone.Width(), rectone.Height());
//Invalidate(TRUE); 如果需要重绘窗口就重绘,如果需要就加上
//pwnd->Invalidate(TRUE); 重绘桌面
}
else
{
MoveWindow(rectPrevWindow.left, rectPrevWindow.top, rectPrevWindow.Width(), rectPrevWindow.Height());
Invalidate(TRUE); //重绘窗口
//CWnd *pwnd = GetDesktopWindow(); // 重绘桌面,如果需要就加上
//pwnd->Invalidate(TRUE);
}
return TRUE;
}
后记:沾满屏幕的实现机制其实差不多。都是得到DesktopWindow的大小,然后缩放想要放大的窗口。至于怎么样应用和响应方式看项目需求。
文档中其他内容是因为我看代码需要了解的,详细看了下。做到知其然而知其所以然。
今天看到代码维护中特别不好的案例,自己要注意代码的维护和休Bug加入的特定的处理部分,一定要写注释,否则后来人会看到一坨屎样的代码。