?? winutil.cpp
字號:
SelectPalette(m_hdc,m_hPalette,m_bBackground || bForceBackground);
SelectPalette(m_MemoryDC,m_hPalette,m_bBackground);
}
// If we grab a critical section here we can deadlock
// with the window thread because one of the side effects
// of RealizePalette is to send a WM_PALETTECHANGED message
// to every window in the system. In our handling
// of WM_PALETTECHANGED we used to grab this CS too.
// The really bad case is when our renderer calls DoRealisePalette()
// while we're in the middle of processing a palette change
// for another window.
// So don't hold the critical section while actually realising
// the palette. In any case USER is meant to manage palette
// handling - we shouldn't have to serialize everything as well
ASSERT(CritCheckOut(&m_WindowLock));
ASSERT(CritCheckOut(&m_PaletteLock));
EXECUTE_ASSERT(RealizePalette(m_hdc) != GDI_ERROR);
EXECUTE_ASSERT(RealizePalette(m_MemoryDC) != GDI_ERROR);
return (GdiFlush() == FALSE ? S_FALSE : S_OK);
}
// This is the global window procedure
LRESULT CALLBACK WndProc(HWND hwnd, // Window handle
UINT uMsg, // Message ID
WPARAM wParam, // First parameter
LPARAM lParam) // Other parameter
{
// Get the window long that holds our window object pointer
// If it is NULL then we are initialising the window in which
// case the object pointer has been passed in the window creation
// structure. IF we get any messages before WM_NCCREATE we will
// pass them to DefWindowProc.
CBaseWindow *pBaseWindow = (CBaseWindow *)GetWindowLongPtr(hwnd,0);
if (pBaseWindow == NULL) {
// Get the structure pointer from the create struct.
// We can only do this for WM_NCCREATE which should be one of
// the first messages we receive. Anything before this will
// have to be passed to DefWindowProc (i.e. WM_GETMINMAXINFO)
// If the message is WM_NCCREATE we set our pBaseWindow pointer
// and will then place it in the window structure
// turn off WS_EX_LAYOUTRTL style for quartz windows
if (uMsg == WM_NCCREATE) {
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x400000);
}
if ((uMsg != WM_NCCREATE)
|| (NULL == (pBaseWindow = *(CBaseWindow**) ((LPCREATESTRUCT)lParam)->lpCreateParams)))
{
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}
// Set the window LONG to be the object who created us
#ifdef DEBUG
SetLastError(0); // because of the way SetWindowLong works
#endif
LONG_PTR rc = SetWindowLongPtr(hwnd, (DWORD) 0, (LONG_PTR) pBaseWindow);
#ifdef DEBUG
if (0 == rc) {
// SetWindowLong MIGHT have failed. (Read the docs which admit
// that it is awkward to work out if you have had an error.)
LONG lasterror = GetLastError();
ASSERT(0 == lasterror);
// If this is not the case we have not set the pBaseWindow pointer
// into the window structure and we will blow up.
}
#endif
}
// See if this is the packet of death
if (uMsg == MsgDestroy && uMsg != 0) {
pBaseWindow->DoneWithWindow();
if (pBaseWindow->m_bDoPostToDestroy) {
EXECUTE_ASSERT(SetEvent((HANDLE)wParam));
}
return 0;
}
return pBaseWindow->OnReceiveMessage(hwnd,uMsg,wParam,lParam);
}
// When the window size changes we adjust our member variables that
// contain the dimensions of the client rectangle for our window so
// that we come to render an image we will know whether to stretch
BOOL CBaseWindow::OnSize(LONG Width, LONG Height)
{
m_Width = Width;
m_Height = Height;
return TRUE;
}
// This function handles the WM_CLOSE message
BOOL CBaseWindow::OnClose()
{
ShowWindow(m_hwnd,SW_HIDE);
return TRUE;
}
// This is called by the worker window thread when it receives a terminate
// message from the window object destructor to delete all the resources we
// allocated during initialisation. By the time the worker thread exits all
// processing will have been completed as the source filter disconnection
// flushes the image pending sample, therefore the GdiFlush should succeed
HRESULT CBaseWindow::UninitialiseWindow()
{
// Have we already cleaned up
if (m_hwnd == NULL) {
ASSERT(m_hdc == NULL);
ASSERT(m_MemoryDC == NULL);
return NOERROR;
}
// Release the window resources
EXECUTE_ASSERT(GdiFlush());
if (m_hdc)
{
EXECUTE_ASSERT(ReleaseDC(m_hwnd,m_hdc));
m_hdc = NULL;
}
if (m_MemoryDC)
{
EXECUTE_ASSERT(DeleteDC(m_MemoryDC));
m_MemoryDC = NULL;
}
// Reset the window variables
m_hwnd = NULL;
return NOERROR;
}
// This is called by the worker window thread after it has created the main
// window and it wants to initialise the rest of the owner objects window
// variables such as the device contexts. We execute this function with the
// critical section still locked. Nothing in this function must generate any
// SendMessage calls to the window because this is executing on the window
// thread so the message will never be processed and we will deadlock
HRESULT CBaseWindow::InitialiseWindow(HWND hwnd)
{
// Initialise the window variables
ASSERT(IsWindow(hwnd));
m_hwnd = hwnd;
if (m_bDoGetDC)
{
EXECUTE_ASSERT(m_hdc = GetDC(hwnd));
EXECUTE_ASSERT(m_MemoryDC = CreateCompatibleDC(m_hdc));
EXECUTE_ASSERT(SetStretchBltMode(m_hdc,COLORONCOLOR));
EXECUTE_ASSERT(SetStretchBltMode(m_MemoryDC,COLORONCOLOR));
}
return NOERROR;
}
HRESULT CBaseWindow::DoCreateWindow()
{
WNDCLASS wndclass; // Used to register classes
BOOL bRegistered; // Is this class registered
HWND hwnd; // Handle to our window
bRegistered = GetClassInfo(m_hInstance, // Module instance
m_pClassName, // Window class
&wndclass); // Info structure
// if the window is to be used for drawing puposes and we are getting a DC
// for the entire lifetime of the window then changes the class style to do
// say so. If we don't set this flag then the DC comes from the cache and is
// really bad.
if (m_bDoGetDC)
{
m_ClassStyles |= CS_OWNDC;
}
if (bRegistered == FALSE) {
// Register the renderer window class
wndclass.lpszClassName = m_pClassName;
wndclass.style = m_ClassStyles;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof(CBaseWindow *);
wndclass.hInstance = m_hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) NULL;
wndclass.lpszMenuName = NULL;
RegisterClass(&wndclass);
}
// Create the frame window. Pass the pBaseWindow information in the
// CreateStruct which allows our message handling loop to get hold of
// the pBaseWindow pointer.
CBaseWindow *pBaseWindow = this; // The owner window object
hwnd = CreateWindowEx(m_WindowStylesEx, // Extended styles
m_pClassName, // Registered name
TEXT("ActiveMovie Window"), // Window title
m_WindowStyles, // Window styles
CW_USEDEFAULT, // Start x position
CW_USEDEFAULT, // Start y position
DEFWIDTH, // Window width
DEFHEIGHT, // Window height
NULL, // Parent handle
NULL, // Menu handle
m_hInstance, // Instance handle
&pBaseWindow); // Creation data
// If we failed signal an error to the object constructor (based on the
// last Win32 error on this thread) then signal the constructor thread
// to continue, release the mutex to let others have a go and exit
if (hwnd == NULL) {
DWORD Error = GetLastError();
return AmHresultFromWin32(Error);
}
// Check the window LONG is the object who created us
ASSERT(GetWindowLongPtr(hwnd, 0) == (LONG_PTR)this);
// Initialise the window and then signal the constructor so that it can
// continue and then finally unlock the object's critical section. The
// window class is left registered even after we terminate the thread
// as we don't know when the last window has been closed. So we allow
// the operating system to free the class resources as appropriate
InitialiseWindow(hwnd);
DbgLog((LOG_TRACE, 2, TEXT("Created window class (%s) HWND(%8.8X)"),
m_pClassName, hwnd));
return S_OK;
}
// The base class provides some default handling and calls DefWindowProc
LRESULT CBaseWindow::OnReceiveMessage(HWND hwnd, // Window handle
UINT uMsg, // Message ID
WPARAM wParam, // First parameter
LPARAM lParam) // Other parameter
{
ASSERT(IsWindow(hwnd));
if (PossiblyEatMessage(uMsg, wParam, lParam))
return 0;
// This is sent by the IVideoWindow SetWindowForeground method. If the
// window is invisible we will show it and make it topmost without the
// foreground focus. If the window is visible it will also be made the
// topmost window without the foreground focus. If wParam is TRUE then
// for both cases the window will be forced into the foreground focus
if (uMsg == m_ShowStageMessage) {
BOOL bVisible = IsWindowVisible(hwnd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
(bVisible ? SWP_NOACTIVATE : 0));
// Should we bring the window to the foreground
if (wParam == TRUE) {
SetForegroundWindow(hwnd);
}
return (LRESULT) 1;
}
// When we go fullscreen we have to add the WS_EX_TOPMOST style to the
// video window so that it comes out above any task bar (this is more
// relevant to WindowsNT than Windows95). However the SetWindowPos call
// must be on the same thread as that which created the window. The
// wParam parameter can be TRUE or FALSE to set and reset the topmost
if (uMsg == m_ShowStageTop) {
HWND HwndTop = (wParam == TRUE ? HWND_TOPMOST : HWND_NOTOPMOST);
BOOL bVisible = IsWindowVisible(hwnd);
SetWindowPos(hwnd, HwndTop, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE |
(wParam == TRUE ? SWP_SHOWWINDOW : 0) |
(bVisible ? SWP_NOACTIVATE : 0));
return (LRESULT) 1;
}
// New palette stuff
if (uMsg == m_RealizePalette) {
ASSERT(m_hwnd == hwnd);
return OnPaletteChange(m_hwnd,WM_QUERYNEWPALETTE);
}
switch (uMsg) {
// Repaint the window if the system colours change
case WM_SYSCOLORCHANGE:
InvalidateRect(hwnd,NULL,FALSE);
return (LRESULT) 1;
// Somebody has changed the palette
case WM_PALETTECHANGED:
OnPaletteChange((HWND)wParam,uMsg);
return (LRESULT) 0;
// We are about to receive the keyboard focus so we ask GDI to realise
// our logical palette again and hopefully it will be fully installed
// without any mapping having to be done during any picture rendering
case WM_QUERYNEWPALETTE:
ASSERT(m_hwnd == hwnd);
return OnPaletteChange(m_hwnd,uMsg);
// do NOT fwd WM_MOVE. the parameters are the location of the parent
// window, NOT what the renderer should be looking at. But we need
// to make sure the overlay is moved with the parent window, so we
// do this.
case WM_MOVE:
if (IsWindowVisible(m_hwnd)) {
PostMessage(m_hwnd,WM_PAINT,0,0);
}
break;
// Store the width and height as useful base class members
case WM_SIZE:
OnSize(LOWORD(lParam), HIWORD(lParam));
return (LRESULT) 0;
// Intercept the WM_CLOSE messages to hide the window
case WM_CLOSE:
OnClose();
return (LRESULT) 0;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
// This handles the Windows palette change messages - if we do realise our
// palette then we return TRUE otherwise we return FALSE. If our window is
// foreground application then we should get first choice of colours in the
// system palette entries. We get best performance when our logical palette
// includes the standard VGA colours (at the beginning and end) otherwise
// GDI may have to map from our palette to the device palette while drawing
LRESULT CBaseWindow::OnPaletteChange(HWND hwnd,UINT Message)
{
// First check we are not changing the palette during closedown
if (m_hwnd == NULL || hwnd == NULL) {
return (LRESULT) 0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -