GME  13
GMEViewOverlay.cpp
Go to the documentation of this file.
00001 // GMEViewOverlay.cpp : implementation file
00002 //
00003 
00004 #include "stdafx.h"
00005 #include "GMEViewOverlay.h"
00006 
00007 
00008 const UINT_PTR ID_TIMER = 1;
00009 
00010 // GMEViewOverlay
00011 
00012 IMPLEMENT_DYNAMIC(GMEViewOverlay, CWnd)
00013 
00014 GMEViewOverlay::GMEViewOverlay()
00015 : m_timerID(0)
00016 {
00017 }
00018 
00019 GMEViewOverlay::~GMEViewOverlay()
00020 {
00021         if (this->m_hWnd)
00022         {
00023                 DestroyWindow();
00024         }
00025 }
00026 
00027 void GMEViewOverlay::OnDraw(CDC* pDC)
00028 {
00029         Gdiplus::Graphics gdip(pDC->m_hDC);
00030         gdip.SetPageUnit(Gdiplus::UnitPixel);
00031 
00032         Gdiplus::Pen pen(Gdiplus::Color::Blue);
00033         CRect rect;
00034         GetWindowRect(&rect);
00035         Gdiplus::Rect grect(rect.left, rect.top, rect.Width(), rect.Height());
00036         VERIFY(gdip.DrawRectangle(&pen, grect) == Gdiplus::Ok);
00037 }
00038 
00039 int GMEViewOverlay::OnCreate(LPCREATESTRUCT lpCreateStruct)
00040 {
00041         lpCreateStruct->dwExStyle |= GMEViewOverlay::exstyle;
00042         lpCreateStruct->style |= GMEViewOverlay::style;
00043         //lpCreateStruct->style |= WS_DISABLED;
00044         // SystemParametersInfo(SPI_GETSELECTIONFADE, 0, &fFade, 0);
00045         //CreateWindowEx(exstyle, 
00046         if (__super::OnCreate(lpCreateStruct) == -1)
00047                 return -1;
00048 
00049         return 0;
00050 }
00051 
00052 template<typename int_>
00053 int_ RoundUpTo4(int_ val)
00054 {
00055         int_ mask = 0;
00056         mask = (~mask) ^ 3;
00057         return (val + 3) & mask;
00058 }
00059 
00060 void GMEViewOverlay::Init1()
00061 {
00062         DWORD exstyle = GMEViewOverlay::exstyle;
00063         DWORD style = GMEViewOverlay::style;
00064 
00065         VERIFY(ModifyStyleEx(0, exstyle));
00066         VERIFY(ModifyStyle(0, style));
00067         //DWORD style = GetStyle();
00068         //DWORD exstyle = GetExStyle();
00069 
00070         GdiFlush();
00071 
00072         CRect rcWindow;
00073         GetWindowRect(&rcWindow);
00074         SIZE size = {rcWindow.Width(), rcWindow.Height()};
00075 
00076         CDC screen;
00077         screen.Attach(::GetDC(NULL));
00078         m_memcdc = new CDC();
00079         m_memcdc->CreateCompatibleDC(&screen);
00080         // LPVOID bitmapdata = VirtualAlloc(0, RoundUpTo4(size.cx) * RoundUpTo4(size.cy) * 4, MEM_COMMIT, PAGE_READWRITE);
00081         // m_bitmap = CreateBitmap(RoundUpTo4(size.cx), RoundUpTo4(size.cy), 1, 32, bitmapdata);
00082         m_bitmap = CreateCompatibleBitmap(screen, size.cx, size.cy);
00083         ASSERT(m_bitmap);
00084 
00085         BITMAPINFO bmpInfo = {0};
00086         bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
00087         GetDIBits(*m_memcdc, m_bitmap, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS);
00088         // TODO check bmpInfo.bmiHeader.biBitCount==32
00089 
00090         HGDIOBJ old = ::SelectObject(*m_memcdc, m_bitmap);
00091         /*/ debugging: draw outline around window
00092         {
00093                 Gdiplus::Graphics gdip(*m_memcdc);
00094                 gdip.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
00095                 gdip.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
00096                 {
00097                 CRect rect;
00098                 GetWindowRect(&rect);
00099                 Gdiplus::Rect grect(0, 0, rect.Width()-1, rect.Height()-1);
00100                 Gdiplus::Pen trans(Gdiplus::Color(254, 255, 0, 0), 1);
00101                 VERIFY(gdip.DrawRectangle(&trans, grect) == Gdiplus::Ok);
00102                 }
00103         }
00104         // */
00105 }
00106 
00107 void GMEViewOverlay::Init2()
00108 {
00109         CRect rcWindow;
00110         GetWindowRect(&rcWindow);
00111         SIZE size = {rcWindow.Width(), rcWindow.Height()};
00112         /* debugging: FillRectangle with alpha==255 results in alpha==0
00113         {
00114                 Gdiplus::Graphics gdip(*m_memcdc);
00115                 gdip.Clear(Gdiplus::Color(0));
00116                 gdip.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
00117                 gdip.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
00118                 // doesnt matter gdip.SetCompositingMode( Gdiplus::CompositingModeSourceCopy ); 
00119                 {
00120                 CRect rect;
00121                 GetWindowRect(&rect);
00122                 Gdiplus::Rect grect(0, 0, 32, rect.Height()/2);
00123                 Gdiplus::SolidBrush trans(Gdiplus::Color(180, 255, 0, 0));
00124                 VERIFY(gdip.FillRectangle(&trans, grect) == Gdiplus::Ok);
00125                 }
00126                 {
00127                 CRect rect;
00128                 GetWindowRect(&rect);
00129                 Gdiplus::Rect grect(32, 0, 50, rect.Height()/2);
00130                 Gdiplus::SolidBrush trans(Gdiplus::Color(255, 250, 0, 0));
00131                 VERIFY(gdip.FillRectangle(&trans, grect) == Gdiplus::Ok);
00132                 }
00133         } */
00134 
00135         BITMAPINFO bmi = {0};
00136         bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
00137         bmi.bmiHeader.biBitCount = 32;
00138         bmi.bmiHeader.biCompression = BI_RGB;
00139         bmi.bmiHeader.biHeight = size.cy;
00140         bmi.bmiHeader.biWidth = size.cx;
00141         bmi.bmiHeader.biPlanes=1;
00142         LPVOID bits = VirtualAlloc(0, RoundUpTo4(size.cx) * RoundUpTo4(size.cy) * 4, MEM_COMMIT, PAGE_READWRITE);
00143         //auto dibits2 = GetDIBits(*m_memcdc, m_bitmap, size.cy/2+9, size.cy/2-10, bits, &bmi, DIB_RGB_COLORS);
00144 
00145         int dibits = GetDIBits(*m_memcdc, m_bitmap, 0, size.cy, bits, &bmi, DIB_RGB_COLORS);
00146         ASSERT(dibits);
00147         // GDI+ sets the alpha value to 0 if the source is 255. fix it
00148         //  (GDI always sets alpha to 0. Fix that too)
00149         for (int i = 0; i < size.cy; i++)
00150         {
00151                 for (int j = 0; j < size.cx; j++)
00152                 {
00153                         int *argb = ((int*)bits) + size.cx * i + j;
00154                         if ((*argb & 0x00FFFFFF) && (*argb & 0xFF000000) == 0)
00155                         {
00156                                 *argb = *argb | 0xFF000000;
00157                         }
00158                         // assert premultiplied
00159                         ASSERT(((*argb & 0xFF000000) >> 24) >= ((*argb & 0x00FF0000) >> 16));
00160                         ASSERT(((*argb & 0xFF000000) >> 24) >= ((*argb & 0x0000FF00) >> 8));
00161                         ASSERT(((*argb & 0xFF000000) >> 24) >= ((*argb & 0x000000FF)));
00162                 }
00163         }
00164         dibits = SetDIBits(*m_memcdc, m_bitmap, 0, size.cy, bits, &bmi, DIB_RGB_COLORS);
00165         VERIFY(dibits);
00166         VirtualFree(bits, 0, MEM_RELEASE);
00167 
00168         //VERIFY(::SelectObject(*m_memcdc, m_bitmap));
00169 
00170         ASSERT(GetSafeHwnd());
00171         ::SetWindowPos(GetSafeHwnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
00172     POINT ptZero = {0, 0};
00173         POINT ptDest = {rcWindow.left+1, rcWindow.top+1};
00174         m_opacity = 0;
00175         BLENDFUNCTION blend = { AC_SRC_OVER, 0, 254, AC_SRC_ALPHA};
00176         CDC screen;
00177         screen.Attach(::GetDC(NULL));
00178         // m_memcdc RGB is premultiplied with alpha
00179         VERIFY(UpdateLayeredWindow(&screen, &ptDest, &size, m_memcdc, &ptZero, 0, &blend, ULW_ALPHA));
00180 
00181         m_timerID = SetTimer(2, 75, NULL);
00182 }
00183 
00184 
00185 BEGIN_MESSAGE_MAP(GMEViewOverlay, CWnd)
00186         ON_WM_CLOSE()
00187         ON_WM_CREATE()
00188         ON_WM_TIMER()
00189 END_MESSAGE_MAP()
00190 
00191 
00192 
00193 // GMEViewOverlay message handlers
00194 
00195 void GMEViewOverlay::OnClose()
00196 {
00197         CWnd::OnClose();
00198 }
00199 
00200 // Fade out, in, then out
00201 //[254 - i * 22  for i in range(6)] + [254 - i * 22  for i in range(6, 0, -1)] + [254 - i * 19  for i in range(13)] + [0]
00202 static BYTE opacities[] = { 254, 232, 210, 188, 166, 144, 122, 144, 166, 188, 210, 232, 254, 235, 216, 197, 178, 159, 140, 121, 102, 83, 64, 45, 26, 0 };
00203 
00204 void GMEViewOverlay::OnTimer(UINT_PTR nIDEvent)
00205 {
00206         m_opacity++;
00207         if (opacities[m_opacity] == 0)
00208         {
00209                 DestroyWindow();
00210                 return;
00211         }
00212         BLENDFUNCTION blend;
00213         blend.BlendOp = AC_SRC_OVER;
00214         blend.BlendFlags = 0;
00215         blend.SourceConstantAlpha = opacities[m_opacity];
00216         blend.AlphaFormat = 0;
00217         blend.AlphaFormat = AC_SRC_ALPHA;
00218  
00219         VERIFY(UpdateLayeredWindow(NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA));
00220 
00221         CWnd::OnTimer(nIDEvent);
00222 }
00223 
00224 BOOL GMEViewOverlay::DestroyWindow()
00225 {
00226         if (m_timerID)
00227         {
00228                 int ret = KillTimer(m_timerID);
00229                 if (ret != 0)
00230                 {
00231                         auto err = GetLastError();
00232                         ASSERT(false);
00233                 }
00234         }
00235         VERIFY(DeleteObject(m_bitmap));
00236         VERIFY(m_memcdc->DeleteDC());
00237 
00238         return CWnd::DestroyWindow();
00239 }