From: Mikko L. <laz...@us...> - 2004-06-19 15:12:34
|
Update of /cvsroot/rtk/rtk/src/gui/VDAL In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12106/gui/VDAL Added Files: Win32_VDAL.cpp Log Message: Added first GUI files. NOTE: Nothing usable yet, just sandbox for developing :) --- NEW FILE: Win32_VDAL.cpp --- // VDAL.cpp: implementation of the VDAL class. // ////////////////////////////////////////////////////////////////////// #include <rtk/Gui.h> #include <rtk/WMAL.h> #include <rtk/Win32_VDAL.h> #include <rtk/Win32_GD.h> #include <rtk/rchar.h> #include <stdlib.h> namespace Rtk { // // WM_SYNCPAINT is an "undocumented" message, which is finally defined in // VC++ 6.0. // #ifndef WM_SYNCPAINT # define WM_SYNCPAINT 0x0088 #endif #ifndef WM_MOUSELEAVE # define WM_MOUSELEAVE 0x02a3 #endif #ifndef WM_MOUSEWHEEL # define WM_MOUSEWHEEL 0x020a #endif #ifndef WHEEL_DELTA # define WHEEL_DELTA 120 // according to MSDN. #endif #ifndef ENUM_CURRENT_SETTINGS # define ENUM_CURRENT_SETTINGS ((DWORD)-1) #endif struct WIN32_VDAL_DATA : public VDAL_DATA { HWND wnd; HBITMAP offscr; HDC dc; HRGN region; Win32GD *gd; unsigned flags; }; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// Win32VDAL::Win32VDAL() { owndc = false; //owndc = true; } Win32VDAL::~Win32VDAL() { } static RCHAR class_name[] = _R("RTK DEFAULT WINDOW CLASS"); int Win32VDAL::Init() { instance = ::GetModuleHandle(NULL); WNDCLASSEX wc; // Documentation states a device context consumes about 800 bytes // of memory... so who cares? If 800 bytes per window is what it // takes to speed things up, I'm game. //wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS; wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; if(owndc) wc.style |= CS_OWNDC; wc.lpfnWndProc = (WNDPROC)Win32VDAL::WndProc; wc.cbClsExtra = wc.cbWndExtra = 0; wc.hInstance = instance; //if (!w->icon()) //w->icon((void *)LoadIcon(NULL, IDI_APPLICATION)); wc.hIcon = wc.hIconSm = 0;//(HICON)w->icon(); wc.hCursor = LoadCursor(NULL, IDC_ARROW); //uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b); //wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(178,178,178)); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = class_name; wc.cbSize = sizeof(WNDCLASSEX); RegisterClassEx(&wc); if( !(WMAL::Instance()->GetCaps() & WMAL::MANAGED) ) { // Create desktop window! // CreateWin(-1, -1, 320, 240, 0, 0, 0); } procid = ::GetCurrentThreadId(); return 1; } int borders(int& dx,int& dy,int& dw,int& dh) { dx = dy = dw = dh = 0; #if 0 if (!window->border() || window->override() || window->parent()) { dx = dy = dw = dh = 0; return WS_POPUP; } // resizable else if (window->m_maxw != window->m_minw || window->m_maxh != window->m_minh) #endif { dx = GetSystemMetrics(SM_CXSIZEFRAME); dw = 2*dx; int bt = GetSystemMetrics(SM_CYCAPTION); int by = GetSystemMetrics(SM_CYSIZEFRAME); dy = bt+by; dh = bt+2*by; return WS_THICKFRAME | WS_MAXIMIZEBOX | WS_CAPTION; } #if 0 else { dx = GetSystemMetrics(SM_CXFIXEDFRAME); dw = 2*dx; int bt = GetSystemMetrics(SM_CYCAPTION); int by = GetSystemMetrics(SM_CYFIXEDFRAME); dy = bt+by; dh = bt+2*by; return WS_DLGFRAME | WS_CAPTION; } #endif } VDALHandle Win32VDAL::CreateWin(int x, int y, int w, int h, unsigned flags, void *data, VDALCallback cb) { DWORD dwStyle = WS_OVERLAPPEDWINDOW /*WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPED | WS_SIZEBOX */| WS_VISIBLE; DWORD dwStyleEx = WS_EX_LEFT; int dx,dy,dw,dh; borders(dx,dy,dw,dh); HWND wnd = ::CreateWindowEx(dwStyleEx, class_name, _R("VDAL Window"), dwStyle, (x==-1) ? CW_USEDEFAULT : (x+dx), (y==-1) ? CW_USEDEFAULT : (y+dy), w+dw, h+dh, NULL, NULL, instance, this); WIN32_VDAL_DATA *ret = (WIN32_VDAL_DATA*)calloc(1, sizeof(WIN32_VDAL_DATA)); ret->wnd = wnd; if(owndc) ret->dc = GetDC(wnd); SetWindowLong(wnd, GWL_USERDATA, (LONG)ret); ret->userdata = data; ret->cb = cb; return ret; } bool Win32VDAL::DestroyWin(VDALHandle win) { WIN32_VDAL_DATA *handle = (WIN32_VDAL_DATA *)win; if(handle->dc) ReleaseDC(handle->wnd, handle->dc); DestroyWindow(handle->wnd); free(handle); return true; } static HDC maindc = NULL; VDALHandle Win32VDAL::CreateOffscreen(int w, int h) { WIN32_VDAL_DATA *ret = (WIN32_VDAL_DATA*)calloc(1, sizeof(WIN32_VDAL_DATA)); if(!maindc) maindc = GetDC(NULL); ret->flags = 1; ret->offscr = CreateCompatibleBitmap(maindc, w, h); ret->dc = CreateCompatibleDC(maindc); SelectObject(ret->dc, ret->offscr); return ret; } bool Win32VDAL::ResizeOffscreen(VDALHandle offscr, int w, int h) { WIN32_VDAL_DATA *handle = (WIN32_VDAL_DATA *)offscr; if(!handle->offscr) return false; DeleteObject(handle->offscr); handle->offscr = CreateCompatibleBitmap(maindc, w, h); SelectObject(handle->dc, handle->offscr); return true; } bool Win32VDAL::DestroyOffscreen(VDALHandle offscr) { WIN32_VDAL_DATA *handle = (WIN32_VDAL_DATA *)offscr; if(!handle->offscr) return false; DeleteDC(handle->dc); DeleteObject(handle->offscr); free(handle); return true; } bool Win32VDAL::Copy(VDALHandle dst, int x, int y, int w, int h, VDALHandle src, int srcx, int srcy) { WIN32_VDAL_DATA *dhandle = (WIN32_VDAL_DATA *)dst; WIN32_VDAL_DATA *shandle = (WIN32_VDAL_DATA *)src; HDC dstdc; HDC srcdc = shandle->dc; if(dhandle->dc) dstdc = dhandle->dc; else { dstdc = GetDC(dhandle->wnd); } BitBlt(dstdc, x, y, w, h, srcdc, srcx, srcy, SRCCOPY); if(!dhandle->dc) { ReleaseDC(dhandle->wnd, dstdc); } return true; } GD *Win32VDAL::CreateGD(VDALHandle win) { WIN32_VDAL_DATA *handle = (WIN32_VDAL_DATA *)win; Win32GD *gd = new Win32GD(); if(!owndc) gd->SetHWND(handle->wnd); else gd->SetHDC(handle->dc); return gd; } GD *Win32VDAL::PrepareGD(VDALHandle win) { WIN32_VDAL_DATA *handle = (WIN32_VDAL_DATA *)win; Win32GD *gd = handle->gd; if(!gd) gd = new Win32GD(); if(handle->dc) gd->SetHDC(handle->dc); else gd->SetHWND(handle->wnd); gd->BeginDraw(); handle->gd = gd; if(handle->region) ::SelectClipRgn(gd->GetHDC(), handle->region); return gd; } void Win32VDAL::UnprepareGD(VDALHandle win, GD *gd) { WIN32_VDAL_DATA *handle = (WIN32_VDAL_DATA *)win; if(gd != handle->gd) { printf("OOPS!! Strange GD..\n"); } else { if(handle->region) ::SelectClipRgn(((Win32GD *)gd)->GetHDC(), NULL); gd->EndDraw(); } } MSG win_msg; // WM_MAKEWAITRETURN is the user-defined message that is used to try // to make WaitEvent() return to the main loop so the windows version acts // like GUI programs on more sensible operating systems #define WM_MAKEWAITRETURN (WM_USER+0x456) int Win32VDAL::WaitEvent(int timeout) { int have_message = 0; int timerid; if(timeout < INFINITE) { have_message = PeekMessage(&win_msg, NULL, 0, 0, PM_REMOVE); if(!have_message) { if(timeout > 0) { // Got some time to wait timerid = SetTimer(NULL, 0, timeout, NULL); have_message = GetMessage(&win_msg, NULL, 0, 0); KillTimer(NULL, timerid); if(win_msg.message == WM_TIMER) have_message = 0; // TIMEOUT! } } } else { have_message = GetMessage(&win_msg, NULL, 0, 0); } if(!have_message) { // No messages in given time (if not infinite), // Return 0 to notify that timeout exceed. return 0; } // Execute the message we got, and all other pending messages: while (have_message) { if(win_msg.message != WM_MAKEWAITRETURN) { TranslateMessage(&win_msg); DispatchMessage(&win_msg); } have_message = PeekMessage(&win_msg, NULL, 0, 0, PM_REMOVE); } // Return 1, since there's some events we have handled. return 1; } void Win32VDAL::Wakeup() { PostThreadMessage(procid, WM_MAKEWAITRETURN, 0, 0); } LRESULT CALLBACK Win32VDAL::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { WIN32_VDAL_DATA *handle = (WIN32_VDAL_DATA *)GetWindowLong(hWnd, GWL_USERDATA); if(!handle) goto RETURN; switch (uMsg) { case WM_SYNCPAINT : case WM_NCPAINT : case WM_ERASEBKGND : // Andreas Weitl - WM_SYNCPAINT needs to be passed to DefWindowProc // so that Windows can generate the proper paint messages... // Similarly, WM_NCPAINT and WM_ERASEBKGND need this, too... break; case WM_CAPTURECHANGED: break; case WM_QUIT: // this should not happen? //Fl::fatal(_T("WM_QUIT message")); break; case WM_CLOSE: if(handle->cb) (handle->cb)(handle, WIN_CLOSE, 0); return 1; case WM_PAINT: { #if 1 // Merge the region into whatever is accumulated by RTK. I do this // by merging the RTK region to the hWnd and reading the resulting region // back: if(handle->region) InvalidateRgn(hWnd, handle->region, FALSE); else handle->region = CreateRectRgn(0,0,0,0); GetUpdateRgn(hWnd, handle->region, 0); // This convinces MSWindows we have painted whatever they wanted // us to paint, and stops it from sending WM_PAINT messages: ValidateRgn(hWnd, handle->region); if(handle->cb) { (handle->cb)(handle, WIN_FLUSH, 0); } ::DeleteObject(handle->region); handle->region = 0; #else PAINTSTRUCT paint; // Save DC HDC saved_dc = handle->dc; // Merge RTK window clip region if(handle->region) { InvalidateRgn(hWnd, handle->region, FALSE); DeleteObject(handle->region); handle->region = 0; } // Begin handles clipping and validating handle->dc = BeginPaint(hWnd, &paint); GD *gd = VDAL::vdal_instance->PrepareGD(handle); Rtk::FlushWindow(handle, gd); VDAL::vdal_instance->UnprepareGD(handle, gd); // Done! EndPaint(hWnd, &paint); // Restore DC handle->dc = saved_dc; #endif break; } case WM_SIZE: { if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) { // iconize } else { if(handle->cb) { long args[3] = { LOWORD(lParam), HIWORD(lParam), 0 }; (handle->cb)(handle, WIN_RESIZE, args); } } break; } default: break; } RETURN: return DefWindowProc(hWnd, uMsg, wParam, lParam); } }; // namespace Rtk |