窗口全屏

相關知識點 學習

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.

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:

 

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.

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.

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中處理這樣的全屏操作。改寫系統默認的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加入的特定的處理部分,一定要寫註釋,否則後來人會看到一坨屎樣的代碼。

發佈了139 篇原創文章 · 獲贊 3 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章