📄 winctrl.cpp
字号:
//------------------------------------------------------------------------------
// File: WinCtrl.cpp
//
// Desc: DirectShow base classes - implements video control interface class.
//
// Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include <streams.h>
// The control interface methods require us to be connected
#define CheckConnected(pin,code) \
{ \
if (pin == NULL) { \
ASSERT(!TEXT("Pin not set")); \
} else if (pin->IsConnected() == FALSE) { \
return (code); \
} \
}
// This checks to see whether the window has a drain. An application can in
// most environments set the owner/parent of windows so that they appear in
// a compound document context (for example). In this case, the application
// would probably like to be told of any keyboard/mouse messages. Therefore
// we pass these messages on untranslated, returning TRUE if we're successful
BOOL WINAPI PossiblyEatMessage(HWND hwndDrain, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (hwndDrain != NULL && !InSendMessage())
{
switch (uMsg)
{
case WM_CHAR:
case WM_DEADCHAR:
case WM_KEYDOWN:
case WM_KEYUP:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MOUSEACTIVATE:
case WM_MOUSEMOVE:
// If we pass this on we don't get any mouse clicks
//case WM_NCHITTEST:
case WM_NCLBUTTONDBLCLK:
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCMBUTTONDBLCLK:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
case WM_NCMOUSEMOVE:
case WM_NCRBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
case WM_RBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
DbgLog((LOG_TRACE, 2, TEXT("Forwarding %x to drain")));
PostMessage(hwndDrain, uMsg, wParam, lParam);
return TRUE;
}
}
return FALSE;
}
// This class implements the IVideoWindow control functions (dual interface)
// we support a large number of properties and methods designed to allow the
// client (whether it be an automation controller or a C/C++ application) to
// set and get a number of window related properties such as it's position.
// We also support some methods that duplicate the properties but provide a
// more direct and efficient mechanism as many values may be changed in one
CBaseControlWindow::CBaseControlWindow(
CBaseFilter *pFilter, // Owning filter
CCritSec *pInterfaceLock, // Locking object
TCHAR *pName, // Object description
LPUNKNOWN pUnk, // Normal COM ownership
HRESULT *phr) : // OLE return code
CBaseVideoWindow(pName,pUnk),
m_pInterfaceLock(pInterfaceLock),
m_hwndOwner(NULL),
m_hwndDrain(NULL),
m_bAutoShow(TRUE),
m_pFilter(pFilter),
m_bCursorHidden(FALSE),
m_pPin(NULL)
{
ASSERT(m_pFilter);
ASSERT(m_pInterfaceLock);
ASSERT(phr);
m_BorderColour = VIDEO_COLOUR;
}
// Set the title caption on the base window, we don't do any field checking
// as we really don't care what title they intend to have. We can always get
// it back again later with GetWindowText. The only other complication is to
// do the necessary string conversions between ANSI and OLE Unicode strings
STDMETHODIMP CBaseControlWindow::put_Caption(BSTR strCaption)
{
CheckPointer(strCaption,E_POINTER);
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
#ifdef UNICODE
SetWindowText(m_hwnd, strCaption);
#else
CHAR Caption[CAPTION];
WideCharToMultiByte(CP_ACP,0,strCaption,-1,Caption,CAPTION,NULL,NULL);
SetWindowText(m_hwnd, Caption);
#endif
return NOERROR;
}
// Get the current base window title caption, once again we do no real field
// checking. We allocate a string for the window title to be filled in with
// which ensures the interface doesn't fiddle around with getting memory. A
// BSTR is a normal C string with the length at position (-1), we use the
// WriteBSTR helper function to create the caption to try and avoid OLE32
STDMETHODIMP CBaseControlWindow::get_Caption(BSTR *pstrCaption)
{
CheckPointer(pstrCaption,E_POINTER);
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
WCHAR WideCaption[CAPTION];
#ifdef UNICODE
GetWindowText(m_hwnd,WideCaption,CAPTION);
#else
// Convert the ASCII caption to a UNICODE string
TCHAR Caption[CAPTION];
GetWindowText(m_hwnd,Caption,CAPTION);
MultiByteToWideChar(CP_ACP,0,Caption,-1,WideCaption,CAPTION);
#endif
return WriteBSTR(pstrCaption,WideCaption);
}
// Set the window style using GWL_EXSTYLE
STDMETHODIMP CBaseControlWindow::put_WindowStyleEx(long WindowStyleEx)
{
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
// Should we be taking off WS_EX_TOPMOST
if (GetWindowLong(m_hwnd,GWL_EXSTYLE) & WS_EX_TOPMOST) {
if ((WindowStyleEx & WS_EX_TOPMOST) == 0) {
SendMessage(m_hwnd,m_ShowStageTop,(WPARAM) FALSE,(LPARAM) 0);
}
}
// Likewise should we be adding WS_EX_TOPMOST
if (WindowStyleEx & WS_EX_TOPMOST) {
SendMessage(m_hwnd,m_ShowStageTop,(WPARAM) TRUE,(LPARAM) 0);
WindowStyleEx &= (~WS_EX_TOPMOST);
if (WindowStyleEx == 0) return NOERROR;
}
return DoSetWindowStyle(WindowStyleEx,GWL_EXSTYLE);
}
// Gets the current GWL_EXSTYLE base window style
STDMETHODIMP CBaseControlWindow::get_WindowStyleEx(long *pWindowStyleEx)
{
CheckPointer(pWindowStyleEx,E_POINTER);
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
return DoGetWindowStyle(pWindowStyleEx,GWL_EXSTYLE);
}
// Set the window style using GWL_STYLE
STDMETHODIMP CBaseControlWindow::put_WindowStyle(long WindowStyle)
{
// These styles cannot be changed dynamically
if ((WindowStyle & WS_DISABLED) ||
(WindowStyle & WS_ICONIC) ||
(WindowStyle & WS_MAXIMIZE) ||
(WindowStyle & WS_MINIMIZE) ||
(WindowStyle & WS_HSCROLL) ||
(WindowStyle & WS_VSCROLL)) {
return E_INVALIDARG;
}
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
return DoSetWindowStyle(WindowStyle,GWL_STYLE);
}
// Get the current GWL_STYLE base window style
STDMETHODIMP CBaseControlWindow::get_WindowStyle(long *pWindowStyle)
{
CheckPointer(pWindowStyle,E_POINTER);
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
return DoGetWindowStyle(pWindowStyle,GWL_STYLE);
}
// Change the base window style or the extended styles depending on whether
// WindowLong is GWL_STYLE or GWL_EXSTYLE. We must call SetWindowPos to have
// the window displayed in it's new style after the change which is a little
// tricky if the window is not currently visible as we realise it offscreen.
// In most cases the client will call get_WindowStyle before they call this
// and then AND and OR in extra bit settings according to the requirements
HRESULT CBaseControlWindow::DoSetWindowStyle(long Style,long WindowLong)
{
RECT WindowRect;
// Get the window's visibility before setting the style
BOOL bVisible = IsWindowVisible(m_hwnd);
EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
// Set the new style flags for the window
SetWindowLong(m_hwnd,WindowLong,Style);
UINT WindowFlags = SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE;
WindowFlags |= SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
// Show the window again in the current position
if (bVisible == TRUE) {
SetWindowPos(m_hwnd, // Base window handle
HWND_TOP, // Just a place holder
0,0,0,0, // Leave size and position
WindowFlags); // Just draw it again
return NOERROR;
}
// Move the window offscreen so the user doesn't see the changes
MoveWindow((HWND) m_hwnd, // Base window handle
GetSystemMetrics(SM_CXSCREEN), // Current desktop width
GetSystemMetrics(SM_CYSCREEN), // Likewise it's height
WIDTH(&WindowRect), // Use the same width
HEIGHT(&WindowRect), // Keep height same to
TRUE); // May as well repaint
// Now show the previously hidden window
SetWindowPos(m_hwnd, // Base window handle
HWND_TOP, // Just a place holder
0,0,0,0, // Leave size and position
WindowFlags); // Just draw it again
ShowWindow(m_hwnd,SW_HIDE);
if (GetParent(m_hwnd)) {
MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2);
}
MoveWindow((HWND) m_hwnd, // Base window handle
WindowRect.left, // Existing x coordinate
WindowRect.top, // Existing y coordinate
WIDTH(&WindowRect), // Use the same width
HEIGHT(&WindowRect), // Keep height same to
TRUE); // May as well repaint
return NOERROR;
}
// Get the current base window style (either GWL_STYLE or GWL_EXSTYLE)
HRESULT CBaseControlWindow::DoGetWindowStyle(long *pStyle,long WindowLong)
{
*pStyle = GetWindowLong(m_hwnd,WindowLong);
return NOERROR;
}
// Change the visibility of the base window, this takes the same parameters
// as the ShowWindow Win32 API does, so the client can have the window hidden
// or shown, minimised to an icon, or maximised to play in full screen mode
// We pass the request on to the base window to actually make the change
STDMETHODIMP CBaseControlWindow::put_WindowState(long WindowState)
{
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
DoShowWindow(WindowState);
return NOERROR;
}
// Get the current window state, this function returns a subset of the SW bit
// settings available in ShowWindow, if the window is visible then SW_SHOW is
// set, if it is hidden then the SW_HIDDEN is set, if it is either minimised
// or maximised then the SW_MINIMIZE or SW_MAXIMIZE is set respectively. The
// other SW bit settings are really set commands not readable output values
STDMETHODIMP CBaseControlWindow::get_WindowState(long *pWindowState)
{
CheckPointer(pWindowState,E_POINTER);
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
ASSERT(pWindowState);
*pWindowState = FALSE;
// Is the window visible, a window is termed visible if it is somewhere on
// the current desktop even if it is completely obscured by other windows
// so the flag is a style for each window set with the WS_VISIBLE bit
if (IsWindowVisible(m_hwnd) == TRUE) {
// Is the base window iconic
if (IsIconic(m_hwnd) == TRUE) {
*pWindowState |= SW_MINIMIZE;
}
// Has the window been maximised
else if (IsZoomed(m_hwnd) == TRUE) {
*pWindowState |= SW_MAXIMIZE;
}
// Window is normal
else {
*pWindowState |= SW_SHOW;
}
} else {
*pWindowState |= SW_HIDE;
}
return NOERROR;
}
// This makes sure that any palette we realise in the base window (through a
// media type or through the overlay interface) is done in the background and
// is therefore mapped to existing device entries rather than taking it over
// as it will do when we this window gets the keyboard focus. An application
// uses this to make sure it doesn't have it's palette removed by the window
STDMETHODIMP CBaseControlWindow::put_BackgroundPalette(long BackgroundPalette)
{
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
CAutoLock cWindowLock(&m_WindowLock);
// Check this is a valid automation boolean type
if (BackgroundPalette != OATRUE) {
if (BackgroundPalette != OAFALSE) {
return E_INVALIDARG;
}
}
// Make sure the window realises any palette it has again
m_bBackground = (BackgroundPalette == OATRUE ? TRUE : FALSE);
PostMessage(m_hwnd,m_RealizePalette,0,0);
PaintWindow(FALSE);
return NOERROR;
}
// This returns the current background realisation setting
STDMETHODIMP
CBaseControlWindow::get_BackgroundPalette(long *pBackgroundPalette)
{
CheckPointer(pBackgroundPalette,E_POINTER);
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
CAutoLock cWindowLock(&m_WindowLock);
// Get the current background palette setting
*pBackgroundPalette = (m_bBackground == TRUE ? OATRUE : OAFALSE);
return NOERROR;
}
// Change the visibility of the base window
STDMETHODIMP CBaseControlWindow::put_Visible(long Visible)
{
CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
// Check this is a valid automation boolean type
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -