窗口全屏

相关知识点 学习

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。

MyOpiniouControlMenu

知道正确答案的请举手!!!!!

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.

valuemeaning
SC_CONTEXTHELPChanges 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_DEFAULTSelects 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 position 

The 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'.

CWnd::IsZoomed

BOOL IsZoomed( ) const;

Return Value

Nonzero if CWnd is maximized; otherwise 0. (从名字很容易误解是判断窗口是否缩放,实际来判断窗口是否处于最大化状态。非0表示窗口已最大化,否则窗口不呈最大化状态.)

Remarks

Determines whether CWnd has been maximized.

 

CWnd::IsIconic

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.

valueaction
GWL_EXSTYLERetrieves the extended window styles. For more information, see CreateWindowEx.
GWL_STYLERetrieves the window styles.
GWL_WNDPROCRetrieves 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_HINSTANCERetrieves a handle to the application instance.
GWL_HWNDPARENTRetrieves a handle to the parent window, if any.
GWL_IDRetrieves the identifier of the window.
GWL_USERDATARetrieves 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.

valueaction
DWL_DLGPROCRetrieves 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_MSGRESULTRetrieves the return value of a message processed in the dialog box procedure.
DWL_USERRetrieves 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.

SetWindowLong

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);

==========================================================

CWnd::ModifyStyle

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加入的特定的处理部分,一定要写注释,否则后来人会看到一坨屎样的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值