WINUTIL.H
//==========================================================================; 
// 
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 
//  PURPOSE. 
// 
//  Copyright (c) 1992 - 1997  Microsoft Corporation.  All Rights Reserved. 
// 
//--------------------------------------------------------------------------; 
 
// Generic window handler base classes, December 1995 
 
// Make sure that you call PrepareWindow to initialise the window after 
// the object has been constructed. It is a separate method so that 
// derived classes can override useful methods like MessageLoop. Also 
// any derived class must call DoneWithWindow in its destructor. If it 
// doesn't a message may be retrieved and call a derived class member 
// function while a thread is executing the base class destructor code 
 
#ifndef __WINUTIL__ 
#define __WINUTIL__ 
 
const int DEFWIDTH = 320;                    // Initial window width 
const int DEFHEIGHT = 240;                   // Initial window height 
const int CAPTION = 256;                     // Maximum length of caption 
const int TIMELENGTH = 50;                   // Maximum length of times 
const int PROFILESTR = 128;                  // Normal profile string 
const WORD PALVERSION = 0x300;               // GDI palette version 
const LONG PALETTE_VERSION = (LONG) 1;       // Initial palette version 
const COLORREF VIDEO_COLOUR = 0;             // Defaults to black background 
const HANDLE hMEMORY = (HANDLE) 0xFFFFFFFF;  // Says to open as memory file 
 
#define WIDTH(x) ((*(x)).right - (*(x)).left) 
#define HEIGHT(x) ((*(x)).bottom - (*(x)).top) 
#define SHOWSTAGE TEXT("WM_SHOWSTAGE") 
#define SHOWSTAGETOP TEXT("WM_SHOWSTAGETOP") 
#define REALIZEPALETTE TEXT("WM_REALIZEPALETTE") 
 
class AM_NOVTABLE CBaseWindow 
{ 
protected: 
 
    HINSTANCE m_hInstance;          // Global module instance handle 
    HWND m_hwnd;                    // Handle for our window 
    HDC m_hdc;                      // Device context for the window 
    LONG m_Width;                   // Client window width 
    LONG m_Height;                  // Client window height 
    BOOL m_bActivated;              // Has the window been activated 
    LPTSTR m_pClassName;            // Static string holding class name 
    DWORD m_ClassStyles;            // Passed in to our constructor 
    DWORD m_WindowStyles;           // Likewise the initial window styles 
    DWORD m_WindowStylesEx;         // And the extended window styles 
    UINT m_ShowStageMessage;        // Have the window shown with focus 
    UINT m_ShowStageTop;            // Makes the window WS_EX_TOPMOST 
    UINT m_RealizePalette;          // Makes us realize our new palette 
    HDC m_MemoryDC;                 // Used for fast BitBlt operations 
    HPALETTE m_hPalette;            // Handle to any palette we may have 
    BYTE m_bNoRealize;              // Don't realize palette now 
    BYTE m_bBackground;             // Should we realise in background 
    BYTE m_bRealizing;              // already realizing the palette 
    CCritSec m_WindowLock;          // Serialise window object access 
    BOOL m_bDoGetDC;                // Should this window get a DC 
 
 
    // Maps windows message procedure into C++ methods 
    friend LRESULT CALLBACK WndProc(HWND hwnd,      // Window handle 
                                    UINT uMsg,      // Message ID 
                                    WPARAM wParam,  // First parameter 
                                    LPARAM lParam); // Other parameter 
 
    virtual LRESULT OnPaletteChange(HWND hwnd, UINT Message); 
 
public: 
 
    CBaseWindow(BOOL bDoGetDC = TRUE); 
 
#ifdef DEBUG 
    virtual ~CBaseWindow(); 
#endif 
 
    virtual HRESULT DoneWithWindow(); 
    virtual HRESULT PrepareWindow(); 
    virtual HRESULT InactivateWindow(); 
    virtual HRESULT ActivateWindow(); 
    virtual BOOL OnSize(LONG Width, LONG Height); 
    virtual BOOL OnClose(); 
    virtual RECT GetDefaultRect(); 
    virtual HRESULT UninitialiseWindow(); 
    virtual HRESULT InitialiseWindow(HWND hwnd); 
 
    HRESULT DoCreateWindow(); 
 
    HRESULT PerformanceAlignWindow(); 
    HRESULT DoShowWindow(LONG ShowCmd); 
    void PaintWindow(BOOL bErase); 
    void DoSetWindowForeground(BOOL bFocus); 
    virtual HRESULT SetPalette(HPALETTE hPalette); 
    void SetRealize(BOOL bRealize) 
    { 
        m_bNoRealize = !bRealize; 
    } 
 
    //  Jump over to the window thread to set the current palette 
    HRESULT SetPalette(); 
 
    virtual HRESULT DoRealisePalette(BOOL bForceBackground = FALSE); 
 
    virtual BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) 
    { return FALSE; }; 
 
    // Access our window information 
 
    LONG GetWindowWidth(); 
    LONG GetWindowHeight(); 
    HWND GetWindowHWND(); 
    HDC GetMemoryHDC(); 
    HDC GetWindowHDC(); 
 
    // This is the window procedure the derived object should override 
 
    virtual LRESULT OnReceiveMessage(HWND hwnd,          // Window handle 
                                     UINT uMsg,          // Message ID 
                                     WPARAM wParam,      // First parameter 
                                     LPARAM lParam);     // Other parameter 
 
    // Must be overriden to return class and window styles 
 
    virtual LPTSTR GetClassWindowStyles( 
                            DWORD *pClassStyles,          // Class styles 
                            DWORD *pWindowStyles,         // Window styles 
                            DWORD *pWindowStylesEx) PURE; // Extended styles 
}; 
 
 
// This helper class is entirely subservient to the owning CBaseWindow object 
// All this object does is to split out the actual drawing operation from the 
// main object (because it was becoming too large). We have a number of entry 
// points to set things like the draw device contexts, to implement the actual 
// drawing and to set the destination rectangle in the client window. We have 
// no critical section locking in this class because we are used exclusively 
// by the owning window object which looks after serialising calls into us 
 
// If you want to use this class make sure you call NotifyAllocator once the 
// allocate has been agreed, also call NotifyMediaType with a pointer to a 
// NON stack based CMediaType once that has been set (we keep a pointer to 
// the original rather than taking a copy). When the palette changes call 
// IncrementPaletteVersion (easiest thing to do is to also call this method 
// in the SetMediaType method most filters implement). Finally before you 
// start rendering anything call SetDrawContext so that we can get the HDCs 
// for drawing from the CBaseWindow object we are given during construction 
 
class CDrawImage 
{ 
protected: 
 
    CBaseWindow *m_pBaseWindow;     // Owning video window object 
    CRefTime m_StartSample;         // Start time for the current sample 
    CRefTime m_EndSample;           // And likewise it's end sample time 
    HDC m_hdc;                      // Main window device context 
    HDC m_MemoryDC;                 // Offscreen draw device context 
    RECT m_TargetRect;              // Target destination rectangle 
    RECT m_SourceRect;              // Source image rectangle 
    BOOL m_bStretch;                // Do we have to stretch the images 
    BOOL m_bUsingImageAllocator;    // Are the samples shared DIBSECTIONs 
    CMediaType *m_pMediaType;       // Pointer to the current format 
    int m_perfidRenderTime;         // Time taken to render an image 
    LONG m_PaletteVersion;          // Current palette version cookie 
 
    // Draw the video images in the window 
 
    void SlowRender(IMediaSample *pMediaSample); 
    void FastRender(IMediaSample *pMediaSample); 
    void DisplaySampleTimes(IMediaSample *pSample); 
    void UpdateColourTable(HDC hdc,BITMAPINFOHEADER *pbmi); 
    void SetStretchMode(); 
 
public: 
 
    // Used to control the image drawing 
 
    CDrawImage(CBaseWindow *pBaseWindow); 
    BOOL DrawImage(IMediaSample *pMediaSample); 
    void SetDrawContext(); 
    void SetTargetRect(RECT *pTargetRect); 
    void SetSourceRect(RECT *pSourceRect); 
    void GetTargetRect(RECT *pTargetRect); 
    void GetSourceRect(RECT *pSourceRect); 
    virtual RECT ScaleSourceRect(const RECT *pSource); 
 
    // Handle updating palettes as they change 
 
    LONG GetPaletteVersion(); 
    void ResetPaletteVersion(); 
    void IncrementPaletteVersion(); 
 
    // Tell us media types and allocator assignments 
 
    void NotifyAllocator(BOOL bUsingImageAllocator); 
    void NotifyMediaType(CMediaType *pMediaType); 
    BOOL UsingImageAllocator(); 
 
    // Called when we are about to draw an image 
 
    void NotifyStartDraw() { 
        MSR_START(m_perfidRenderTime); 
    }; 
 
    // Called when we complete an image rendering 
 
    void NotifyEndDraw() { 
        MSR_STOP(m_perfidRenderTime); 
    }; 
}; 
 
 
// This is the structure used to keep information about each GDI DIB. All the 
// samples we create from our allocator will have a DIBSECTION allocated to 
// them. When we receive the sample we know we can BitBlt straight to an HDC 
 
typedef struct tagDIBDATA { 
 
    LONG        PaletteVersion;     // Current palette version in use 
    DIBSECTION  DibSection;         // Details of DIB section allocated 
    HBITMAP     hBitmap;            // Handle to bitmap for drawing 
    HANDLE      hMapping;           // Handle to shared memory block 
    BYTE        *pBase;             // Pointer to base memory address 
 
} DIBDATA; 
 
 
// This class inherits from CMediaSample and uses all of it's methods but it 
// overrides the constructor to initialise itself with the DIBDATA structure 
// When we come to render an IMediaSample we will know if we are using our own 
// allocator, and if we are, we can cast the IMediaSample to a pointer to one 
// of these are retrieve the DIB section information and hence the HBITMAP 
 
class CImageSample : public CMediaSample 
{ 
protected: 
 
    DIBDATA m_DibData;      // Information about the DIBSECTION 
    BOOL m_bInit;           // Is the DIB information setup 
 
public: 
 
    // Constructor 
 
    CImageSample(CBaseAllocator *pAllocator, 
                 TCHAR *pName, 
                 HRESULT *phr, 
                 LPBYTE pBuffer, 
                 LONG length); 
 
    // Maintain the DIB/DirectDraw state 
 
    void SetDIBData(DIBDATA *pDibData); 
    DIBDATA *GetDIBData(); 
}; 
 
 
// This is an allocator based on the abstract CBaseAllocator base class that 
// allocates sample buffers in shared memory. The number and size of these 
// are determined when the output pin calls Prepare on us. The shared memory 
// blocks are used in subsequent calls to GDI CreateDIBSection, once that 
// has been done the output pin can fill the buffers with data which will 
// then be handed to GDI through BitBlt calls and thereby remove one copy 
 
class CImageAllocator : public CBaseAllocator 
{ 
protected: 
 
    CBaseFilter *m_pFilter;   // Delegate reference counts to 
    CMediaType *m_pMediaType;           // Pointer to the current format 
 
    // Used to create and delete samples 
 
    HRESULT Alloc(); 
    void Free(); 
 
    // Manage the shared DIBSECTION and DCI/DirectDraw buffers 
 
    HRESULT CreateDIB(LONG InSize,DIBDATA &DibData); 
    STDMETHODIMP CheckSizes(ALLOCATOR_PROPERTIES *pRequest); 
    virtual CImageSample *CreateImageSample(LPBYTE pData,LONG Length); 
 
public: 
 
    // Constructor and destructor 
 
    CImageAllocator(CBaseFilter *pFilter,TCHAR *pName,HRESULT *phr); 
#ifdef DEBUG 
    ~CImageAllocator(); 
#endif 
 
    STDMETHODIMP_(ULONG) NonDelegatingAddRef(); 
    STDMETHODIMP_(ULONG) NonDelegatingRelease(); 
    void NotifyMediaType(CMediaType *pMediaType); 
 
    // Agree the number of buffers to be used and their size 
 
    STDMETHODIMP SetProperties( 
        ALLOCATOR_PROPERTIES *pRequest, 
        ALLOCATOR_PROPERTIES *pActual); 
}; 
 
 
// This class is a fairly specialised helper class for image renderers that 
// have to create and manage palettes. The CBaseWindow class looks after 
// realising palettes once they have been installed. This class can be used 
// to create the palette handles from a media format (which must contain a 
// VIDEOINFO structure in the format block). We try to make the palette an 
// identity palette to maximise performance and also only change palettes 
// if actually required to (we compare palette colours before updating). 
// All the methods are virtual so that they can be overriden if so required 
 
class CImagePalette 
{ 
protected: 
 
    CBaseWindow *m_pBaseWindow;             // Window to realise palette in 
    CBaseFilter *m_pFilter;       // Media filter to send events 
    CDrawImage *m_pDrawImage;               // Object who will be drawing 
    HPALETTE m_hPalette;                    // The palette handle we own 
 
public: 
 
    CImagePalette(CBaseFilter *pBaseFilter, 
                  CBaseWindow *pBaseWindow, 
                  CDrawImage *pDrawImage); 
 
#ifdef DEBUG 
    virtual ~CImagePalette(); 
#endif 
 
    static HPALETTE MakePalette(const VIDEOINFOHEADER *pVideoInfo, LPSTR szDevice); 
    HRESULT RemovePalette(); 
    static HRESULT MakeIdentityPalette(PALETTEENTRY *pEntry,INT iColours, LPSTR szDevice); 
    HRESULT CopyPalette(const CMediaType *pSrc,CMediaType *pDest); 
    BOOL ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,const VIDEOINFOHEADER *pOldInfo); 
    HRESULT PreparePalette(const CMediaType *pmtNew,const CMediaType *pmtOld,LPSTR szDevice); 
}; 
 
 
// Another helper class really for video based renderers. Most such renderers 
// need to know what the display format is to some degree or another. This 
// class initialises itself with the display format. The format can be asked 
// for through GetDisplayFormat and various other accessor functions. If a 
// filter detects a display format change (perhaps it gets a WM_DEVMODECHANGE 
// message then it can call RefreshDisplayType to reset that format). Also 
// many video renderers will want to check formats as they are proposed by 
// source filters. This class provides methods to check formats and only 
// accept those video formats that can be efficiently drawn using GDI calls 
 
class CImageDisplay : public CCritSec 
{ 
protected: 
 
    // This holds the display format; biSize should not be too big, so we can 
    // safely use the VIDEOINFO structure 
    VIDEOINFO m_Display; 
 
    static DWORD CountSetBits(const DWORD Field); 
    static DWORD CountPrefixBits(const DWORD Field); 
    static BOOL CheckBitFields(const VIDEOINFO *pInput); 
 
public: 
 
    // Constructor and destructor 
 
    CImageDisplay(); 
 
    // Used to manage BITMAPINFOHEADERs and the display format 
 
    const VIDEOINFO *GetDisplayFormat(); 
    HRESULT RefreshDisplayType(LPSTR szDeviceName); 
    static BOOL CheckHeaderValidity(const VIDEOINFO *pInput); 
    static BOOL CheckPaletteHeader(const VIDEOINFO *pInput); 
    BOOL IsPalettised(); 
    WORD GetDisplayDepth(); 
 
    // Provide simple video format type checking 
 
    HRESULT CheckMediaType(const CMediaType *pmtIn); 
    HRESULT CheckVideoType(const VIDEOINFO *pInput); 
    HRESULT UpdateFormat(VIDEOINFO *pVideoInfo); 
    const DWORD *GetBitMasks(const VIDEOINFO *pVideoInfo); 
 
    BOOL GetColourMask(DWORD *pMaskRed, 
                       DWORD *pMaskGreen, 
                       DWORD *pMaskBlue); 
}; 
 
#endif // __WINUTIL__