📄 window.cpp
字号:
/* * * window.cpp * Copyright (C) 2006 Michael H. Overlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact at poster_printer@yahoo.com */#include "window.h"#include "gdiutils.h"#include "mathutils.h"#include "sprite.h"// **// ** PUBLIC// **Window::Window(HINSTANCE hinst, HWND hwnd, PaintMode pm) { m_hinst = hinst; m_hwnd = hwnd; m_ptScroll.x = m_ptScroll.y = 0; ::ZeroMemory(&m_rScroll, sizeof(m_rScroll)); m_pm = pm; m_bEraseBufferBkg = FALSE; ::GetClientRect(m_hwnd, &m_rClient); m_hrgnUpdate = ::CreateRectRgn(0,0,0,0); m_hrgnEmpty = ::CreateRectRgn(0,0,0,0); m_hbmpBuffer = NULL; this->m_hbmpBuffer = NULL; this->m_bHasBkClr = FALSE; this->m_bkClr = RGB(0xff, 0xff, 0xff); this->SizePaintBuffer(); // SPRITE m_ps = NULL; m_bUpdateSpriteWithWindow = FALSE;}Window::~Window() { if (m_hrgnUpdate != NULL) { ::DeleteObject(m_hrgnUpdate); } if (m_hrgnEmpty != NULL) { ::DeleteObject(m_hrgnEmpty); } if (m_hbmpBuffer != NULL) { ::DeleteObject(m_hbmpBuffer); }}BOOL Window::InvalidateRect(const RECT& r, BOOL bErase) { BOOL bRetValue = TRUE; switch(m_pm) { case Window::ePaintDirect: bRetValue = ::InvalidateRect(m_hwnd, &r, bErase); break; case Window::ePaintBuffered: { // 7/7 NOTE: // DEBUG/FIX THE "ERASE" SETTINGS MAY DIFFER FROM ONE REGION TO ANOTHER // IF WE WANTED, WE COULD KEEP TRACK OF A SEPARATE SUB-REGION THAT NEEDS TO BE ERASED // RATHER THAN TURNING ERAASING ON FOR THE ENTIRE UPDATE REGION if (bErase) { m_bEraseBufferBkg = TRUE; } HRGN hrgnTemp = ::CreateRectRgn(r.left, r.top, r.right, r.bottom); ::CombineRgn(m_hrgnUpdate, m_hrgnUpdate, hrgnTemp, RGN_OR); ::DeleteObject(hrgnTemp); ::InvalidateRect(m_hwnd, &r, FALSE); bRetValue = TRUE; } break; default: ASSERTFAIL(); break; } return bRetValue;}BOOL Window::InvalidateRgn(HRGN hrgn, BOOL bErase) { BOOL bRetValue = TRUE; switch(m_pm) { case Window::ePaintDirect: bRetValue = ::InvalidateRgn(m_hwnd, hrgn, bErase); break; case Window::ePaintBuffered: { if (bErase) { m_bEraseBufferBkg = TRUE; } ::CombineRgn(m_hrgnUpdate, m_hrgnUpdate, hrgn, RGN_OR); ::InvalidateRgn(m_hwnd, hrgn, FALSE); } break; default: ASSERTFAIL(); break; } return TRUE;}void Window::DoUpdateDirectLayer(UpdateDirectLayer& dp) { HDC hdc = this->GetDC(); dp.PaintDirect(hdc); this->ReleaseDC(hdc);}void Window::SetSprite(Sprite *ps) { m_ps = ps;}// THIS COULD BE DONE AS A DIRECT DRAW, YES ?void Window::DoUpdateSprite(void) { HDC hdc = ::GetDC(m_hwnd); Window::BackBufferDCInfo bbdi; HDC hdcMem = this->CreateBackBufferDC(bbdi, hdc); HRGN hrgnUpdate = ::CreateEmptyRgn(); m_ps->Update(hdcMem, hrgnUpdate); //CLIPPING DEVICE VS LOGICAL COORDS?? ::SelectClipRgn(hdc, hrgnUpdate); ::BitBlt(hdc, 0, 0, RW(m_rClient), RH(m_rClient), hdcMem, 0, 0, SRCCOPY); this->PaintDirectLayer(hdc); this->DeleteBackBufferDC(bbdi); ::ReleaseDC(m_hwnd, hdc);}void Window::SetBackgroundColor(COLORREF clr) { if (clr != m_bkClr) { m_bHasBkClr = TRUE; m_bkClr = clr; this->InvalidateRect(this->m_rClient, TRUE); }}// NOTE: IMPLEMENTATION ASSUMES THAT rSrcScroll REMAINS FIXED UNTIL A WM_PAINT OCCURS// ALSO, ONLY BEEN TESTED FOR THE ePaintBuffered CASE// ALSO, IT ASSUMES THAT IF THERE IS A SPRITE IT IS ENTIRELY WITHIN THE REGION BEING// SCROLLED -- SO IMPLEMENTATION IS NOT REALLY COMPLETE YET, BUT DOES WORK UNDER THESE ASSUMPTIONSvoid Window::ScrollWindow(int dx, int dy, const RECT& rSrcScroll) { switch(m_pm) { case ePaintDirect: ::ScrollWindowEx(m_hwnd, dx, dy, &rSrcScroll, NULL, NULL, NULL, SW_INVALIDATE | SW_ERASE); // DEBUG/FIX if (m_ps != NULL) { POINT ptDelta = { dx, dy }; m_ps->Scroll(ptDelta); } break; case ePaintBuffered: m_ptScroll.x += dx; m_ptScroll.y += dy; m_rScroll = rSrcScroll; //7/7 DEBUG/FIX EXTRA CHANGE AFTER WORKING //::InvalidateRect(m_hwnd, &rSrcScroll, TRUE); ::InvalidateRect(m_hwnd, &rSrcScroll, FALSE); break; default: ASSERTFAIL(); break; }}HWND Window::AddArgumentAsNotifyTarget(HWND hwnd) { this->m_vhwndNotify.push_back(hwnd); return m_hwnd;}HWND Window::AddToArgumentsNotifyTargetList(Window *pw) { return pw->AddArgumentAsNotifyTarget(m_hwnd);}LPTSTR Window::GetWindowText(void) const { LPTSTR lptstr = ::MyGetWindowText(m_hwnd); return lptstr;}LRESULT Window::SendNotification(IN HWND hwnd, NMHDR *pnmh) { LRESULT lRetValue = ::SendMessage(hwnd, WM_NOTIFY, pnmh->idFrom, (LPARAM) pnmh); for(uint ui = 0; ui < m_vhwndNotify.size(); ++ui) { HWND hwndTarget = m_vhwndNotify[ui]; ::SendMessage(hwndTarget, WM_NOTIFY, pnmh->idFrom, (LPARAM) pnmh); } return lRetValue;}LRESULT Window::SendNotification(IN UINT code) { NMHDR nmh = { m_hwnd, this->GetDlgCtrlID(), code }; LRESULT lRetValue = this->SendNotification(GetParent(), &nmh); return lRetValue;}// **// ** PROTECTED// **void Window::Paint(HDC hdc) { // DO NOTHING}void Window::PaintDirectLayer(HDC hdc) { // DO NOTHING}void Window::CursorMsg(OUT MSGRESULT& mr, UINT msg, WPARAM wParam, LPARAM lParam) { mr.bProcessed = FALSE;}void Window::KeyboardMsg(OUT MSGRESULT& mr, UINT msg, WPARAM wParam, LPARAM lParam) { mr.bProcessed = FALSE;}void Window::MouseMsg(OUT MSGRESULT& mr, UINT msg, WPARAM wParam, LPARAM lParam) { mr.bProcessed = FALSE;}void Window::NotificationMsg(OUT MSGRESULT& mr, UINT msg, WPARAM wParam, LPARAM lParam) { mr.bProcessed = FALSE; switch(msg) { case WM_SIZE: ::GetClientRect(m_hwnd, &m_rClient); this->SizePaintBuffer(); break; default: break; }}void Window::NotifyMsg(OUT MSGRESULT& mr, WPARAM wParam, LPARAM lParam) { mr.bProcessed = FALSE;}void Window::PaintMsg(OUT MSGRESULT& mr, UINT msg, WPARAM wParam, LPARAM lParam) { if (m_pm == Window::ePaintBuffered && (m_ptScroll.x != 0 || m_ptScroll.y != 0)) { int dx = m_ptScroll.x; int dy = m_ptScroll.y; m_ptScroll.x = m_ptScroll.y = 0; RECT rSrcScroll = m_rScroll; HRGN hrgnTemp = ::CreateRectRgnIndirect(&rSrcScroll); RECT rTemp = rSrcScroll; ::OffsetRect(&rTemp, dx, dy); HRGN hrgnTemp2 = ::CreateRectRgnIndirect(&rTemp); HRGN hrgnTemp3 = ::CreateRectRgn(0,0,0,0); ::CombineRgn(hrgnTemp3, hrgnTemp, hrgnTemp2, RGN_DIFF); ::CombineRgn(m_hrgnUpdate, m_hrgnUpdate, hrgnTemp3, RGN_OR); //7/7 DEBUG/FIX EXTRA CHANGE AFTER WORKING -- THIS ISN'T NEEDED //::InvalidateRect(m_hwnd, &rSrcScroll, TRUE); m_bEraseBufferBkg = TRUE; // ?? ::DeleteObject(hrgnTemp); ::DeleteObject(hrgnTemp2); ::DeleteObject(hrgnTemp3); Window::BackBufferDCInfo bbdi; HDC hdcMem = this->CreateBackBufferDC(bbdi, NULL); SIZE sz = { RW(rSrcScroll), RH(rSrcScroll) }; int x1 = max(dx, 0); int y1 = max(dy, 0); int x2 = - min(dx, 0); int y2 = - min(dy, 0); int adx = abs(dx); int ady = abs(dy); ::BitBlt(hdcMem, rSrcScroll.left + x1, rSrcScroll.top + y1, sz.cx - adx, sz.cy - ady, hdcMem, rSrcScroll.left + x2, rSrcScroll.top + y2, SRCCOPY); this->DeleteBackBufferDC(bbdi); if (m_ps != NULL) { POINT ptDelta = { dx, dy }; m_ps->Scroll(ptDelta); //HRGN hrgn = m_ps->GetUpdateRegion(); } } switch(msg) { case WM_ERASEBKGND: switch(m_pm) { case Window::ePaintDirect: if (this->m_bHasBkClr) { HDC hdc = (HDC) wParam; ::FillSolidColor(hdc, m_rClient, m_bkClr); mr.lRetValue = 0; mr.bProcessed = TRUE; } break; case Window::ePaintBuffered: mr.lRetValue = 0; mr.bProcessed = TRUE; break; default: ASSERTFAIL(); break; } break; case WM_PAINT: { HRGN hrgnMeta = NULL; switch(m_pm) { case ePaintDirect: ::GetUpdateRgn(m_hwnd, m_hrgnUpdate, FALSE); break; case ePaintBuffered: hrgnMeta = ::CreateRectRgn(0,0,0,0); ::GetUpdateRgn(m_hwnd, hrgnMeta, FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -