123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- /* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
- *
- * This 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 software 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 software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
- // Win32Util.cxx
-
- #include <rfb_win32/Win32Util.h>
- #include <rdr/Exception.h>
- #include <rdr/HexOutStream.h>
-
-
- namespace rfb {
- namespace win32 {
-
- LogicalPalette::LogicalPalette() : palette(0), numEntries(0) {
- BYTE buf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
- LOGPALETTE* logpal = (LOGPALETTE*)buf;
- logpal->palVersion = 0x300;
- logpal->palNumEntries = 256;
- for (int i=0; i<256;i++) {
- logpal->palPalEntry[i].peRed = 0;
- logpal->palPalEntry[i].peGreen = 0;
- logpal->palPalEntry[i].peBlue = 0;
- logpal->palPalEntry[i].peFlags = 0;
- }
- palette = CreatePalette(logpal);
- if (!palette)
- throw rdr::SystemException("failed to CreatePalette", GetLastError());
- }
-
- LogicalPalette::~LogicalPalette() {
- if (palette)
- if (!DeleteObject(palette))
- throw rdr::SystemException("del palette failed", GetLastError());
- }
-
- void LogicalPalette::setEntries(int start, int count, const Colour* cols) {
- if (numEntries < count) {
- ResizePalette(palette, start+count);
- numEntries = start+count;
- }
- PALETTEENTRY* logpal = new PALETTEENTRY[count];
- for (int i=0; i<count; i++) {
- logpal[i].peRed = cols[i].r >> 8;
- logpal[i].peGreen = cols[i].g >> 8;
- logpal[i].peBlue = cols[i].b >> 8;
- logpal[i].peFlags = 0;
- }
- UnrealizeObject(palette);
- SetPaletteEntries(palette, start, count, logpal);
- delete [] logpal;
- }
-
-
- static LogWriter dcLog("DeviceContext");
-
- PixelFormat DeviceContext::getPF() const {
- return getPF(dc);
- }
-
- PixelFormat DeviceContext::getPF(HDC dc) {
- PixelFormat format;
- CompatibleBitmap bitmap(dc, 1, 1);
-
- // -=- Get the bitmap format information
- BitmapInfo bi;
- memset(&bi, 0, sizeof(bi));
- bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bi.bmiHeader.biBitCount = 0;
-
- if (!::GetDIBits(dc, bitmap, 0, 1, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
- throw rdr::SystemException("unable to determine device pixel format", GetLastError());
- }
- if (!::GetDIBits(dc, bitmap, 0, 1, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
- throw rdr::SystemException("unable to determine pixel shifts/palette", GetLastError());
- }
-
- // -=- Munge the bitmap info here
- switch (bi.bmiHeader.biBitCount) {
- case 1:
- case 4:
- bi.bmiHeader.biBitCount = 8;
- break;
- case 24:
- bi.bmiHeader.biBitCount = 32;
- break;
- }
- bi.bmiHeader.biPlanes = 1;
-
- format.trueColour = bi.bmiHeader.biBitCount > 8;
- format.bigEndian = 0;
- format.bpp = format.depth = bi.bmiHeader.biBitCount;
-
- if (format.trueColour) {
- DWORD rMask=0, gMask=0, bMask=0;
-
- // Which true colour format is the DIB section using?
- switch (bi.bmiHeader.biCompression) {
- case BI_RGB:
- // Default RGB layout
- switch (bi.bmiHeader.biBitCount) {
- case 16:
- // RGB 555 - High Colour
- dcLog.info("16-bit High Color");
- rMask = 0x7c00;
- bMask = 0x001f;
- gMask = 0x03e0;
- format.depth = 15;
- break;
- case 24:
- case 32:
- // RGB 888 - True Colour
- dcLog.info("24/32-bit High Color");
- rMask = 0xff0000;
- gMask = 0x00ff00;
- bMask = 0x0000ff;
- format.depth = 24;
- break;
- default:
- dcLog.error("bits per pixel %u not supported", bi.bmiHeader.biBitCount);
- throw rdr::Exception("unknown bits per pixel specified");
- };
- break;
- case BI_BITFIELDS:
- // Custom RGB layout
- rMask = bi.mask.red;
- gMask = bi.mask.green;
- bMask = bi.mask.blue;
- dcLog.info("BitFields format: %lu, (%lx, %lx, %lx)",
- bi.bmiHeader.biBitCount, rMask, gMask, bMask);
- if (format.bpp == 32)
- format.depth = 24; // ...probably
- break;
- };
-
- // Convert the data we just retrieved
- initMaxAndShift(rMask, &format.redMax, &format.redShift);
- initMaxAndShift(gMask, &format.greenMax, &format.greenShift);
- initMaxAndShift(bMask, &format.blueMax, &format.blueShift);
- }
-
- return format;
- }
-
-
- WindowDC::WindowDC(HWND wnd) : hwnd(wnd) {
- dc = GetDC(wnd);
- if (!dc)
- throw rdr::SystemException("GetDC failed", GetLastError());
- }
- WindowDC::~WindowDC() {
- if (dc)
- ReleaseDC(hwnd, dc);
- }
-
-
- CompatibleDC::CompatibleDC(HDC existing) {
- dc = CreateCompatibleDC(existing);
- if (!dc)
- throw rdr::SystemException("CreateCompatibleDC failed", GetLastError());
- }
- CompatibleDC::~CompatibleDC() {
- if (dc)
- DeleteDC(dc);
- }
-
-
- BitmapDC::BitmapDC(HDC hdc, HBITMAP hbitmap) : CompatibleDC(hdc){
- oldBitmap = (HBITMAP)SelectObject(dc, hbitmap);
- if (!oldBitmap)
- throw rdr::SystemException("SelectObject to CompatibleDC failed",
- GetLastError());
- }
- BitmapDC::~BitmapDC() {
- SelectObject(dc, oldBitmap);
- }
-
-
- CompatibleBitmap::CompatibleBitmap(HDC hdc, int width, int height) {
- hbmp = CreateCompatibleBitmap(hdc, width, height);
- if (!hbmp)
- throw rdr::SystemException("CreateCompatibleBitmap() failed",
- GetLastError());
- }
- CompatibleBitmap::~CompatibleBitmap() {
- if (hbmp) DeleteObject(hbmp);
- }
-
-
- PaletteSelector::PaletteSelector(HDC dc, HPALETTE pal) : device(dc), redrawRequired(false) {
- oldPal = SelectPalette(dc, pal, FALSE);
- redrawRequired = RealizePalette(dc) > 0;
- }
- PaletteSelector::~PaletteSelector() {
- if (oldPal) SelectPalette(device, oldPal, TRUE);
- }
-
-
- IconInfo::IconInfo(HICON icon) {
- if (!GetIconInfo(icon, this))
- throw rdr::SystemException("GetIconInfo() failed", GetLastError());
- }
- IconInfo::~IconInfo() {
- if (hbmColor)
- DeleteObject(hbmColor);
- if (hbmMask)
- DeleteObject(hbmMask);
- }
-
-
- ModuleFileName::ModuleFileName(HMODULE module) : TCharArray(MAX_PATH) {
- if (!module) module = GetModuleHandle(0);
- if (!GetModuleFileName(module, buf, MAX_PATH))
- buf[0] = 0;
- }
-
-
- FileVersionInfo::FileVersionInfo(const TCHAR* filename) {
- // Get executable name
- ModuleFileName exeName;
- if (!filename) filename = exeName.buf;
-
- // Get version info size
- DWORD handle;
- int size = GetFileVersionInfoSize((TCHAR*)filename, &handle);
- if (!size)
- throw rdr::SystemException("GetVersionInfoSize failed", GetLastError());
-
- // Get version info
- buf = new TCHAR[size];
- if (!GetFileVersionInfo((TCHAR*)filename, handle, size, buf))
- throw rdr::SystemException("GetVersionInfo failed", GetLastError());
- }
-
- const TCHAR* FileVersionInfo::getVerString(const TCHAR* name, DWORD langId) {
- char langIdBuf[sizeof(langId)];
- for (int i=sizeof(langIdBuf)-1; i>=0; i--) {
- langIdBuf[i] = langId & 0xff;
- langId = langId >> 8;
- }
-
- TCharArray langIdStr = rdr::HexOutStream::binToHexStr(langIdBuf, sizeof(langId));
- TCharArray infoName(_tcslen(_T("StringFileInfo")) + 4 + _tcslen(name) + _tcslen(langIdStr.buf));
- _stprintf(infoName.buf, _T("\\StringFileInfo\\%s\\%s"), langIdStr.buf, name);
-
- // Locate the required version string within the version info
- TCHAR* buffer = 0;
- UINT length = 0;
- if (!VerQueryValue(buf, infoName.buf, (void**)&buffer, &length)) {
- printf("unable to find %s version string", CStr(infoName.buf));
- throw rdr::Exception("VerQueryValue failed");
- }
- return buffer;
- }
-
-
- bool splitPath(const TCHAR* path, TCHAR** dir, TCHAR** file) {
- return tstrSplit(path, '\\', dir, file, true);
- }
-
-
- static LogWriter dfbLog("DynamicFn");
-
- DynamicFnBase::DynamicFnBase(const TCHAR* dllName, const char* fnName) : dllHandle(0), fnPtr(0) {
- dllHandle = LoadLibrary(dllName);
- if (!dllHandle) {
- dfbLog.info("DLL %s not found (%d)", (const char*)CStr(dllName), GetLastError());
- return;
- }
- fnPtr = GetProcAddress(dllHandle, fnName);
- if (!fnPtr)
- dfbLog.info("proc %s not found in %s (%d)", fnName, (const char*)CStr(dllName), GetLastError());
- }
-
- DynamicFnBase::~DynamicFnBase() {
- if (dllHandle)
- FreeLibrary(dllHandle);
- }
-
-
- static LogWriter miLog("MonitorInfo");
-
- MonitorInfo::MonitorInfo(HWND window) {
- #if (WINVER >= 0x0500)
- typedef HMONITOR (WINAPI *_MonitorFromWindow_proto)(HWND,DWORD);
- rfb::win32::DynamicFn<_MonitorFromWindow_proto> _MonitorFromWindow(_T("user32.dll"), "MonitorFromWindow");
- typedef BOOL (WINAPI *_GetMonitorInfo_proto)(HMONITOR,LPMONITORINFO);
- rfb::win32::DynamicFn<_GetMonitorInfo_proto> _GetMonitorInfo(_T("user32.dll"), "GetMonitorInfoA");
-
- // Can we dynamically link to the monitor functions?
- if (_MonitorFromWindow.isValid()) {
- if (_GetMonitorInfo.isValid()) {
- HMONITOR monitor = (*_MonitorFromWindow)(window, MONITOR_DEFAULTTONEAREST);
- miLog.debug("monitor=%lx", monitor);
- if (monitor) {
- memset(this, 0, sizeof(MONITORINFOEXA));
- cbSize = sizeof(MONITORINFOEXA);
- if ((*_GetMonitorInfo)(monitor, this)) {
- miLog.debug("monitor is %d,%d-%d,%d", rcMonitor.left, rcMonitor.top, rcMonitor.right, rcMonitor.bottom);
- miLog.debug("work area is %d,%d-%d,%d", rcWork.left, rcWork.top, rcWork.right, rcWork.bottom);
- miLog.debug("device is \"%s\"", szDevice);
- return;
- }
- miLog.error("failed to get monitor info: %ld", GetLastError());
- }
- } else {
- miLog.debug("GetMonitorInfo not found");
- }
- } else {
- miLog.debug("MonitorFromWindow not found");
- }
- #else
- #pragma message ("not building in GetMonitorInfo")
- cbSize = sizeof(MonitorInfo);
- szDevice[0] = 0;
- #endif
-
- // Legacy fallbacks - just return the desktop settings
- miLog.debug("using legacy fall-backs");
- HWND desktop = GetDesktopWindow();
- GetWindowRect(desktop, &rcMonitor);
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
- dwFlags = 0;
- }
-
-
- #if (WINVER >= 0x0500)
-
- struct moveToMonitorData {
- HWND window;
- const char* monitorName;
- };
-
- typedef BOOL (WINAPI *_GetMonitorInfo_proto)(HMONITOR,LPMONITORINFO);
- static rfb::win32::DynamicFn<_GetMonitorInfo_proto> _GetMonitorInfo(_T("user32.dll"), "GetMonitorInfoA");
-
- static BOOL CALLBACK moveToMonitorEnumProc(HMONITOR monitor,
- HDC dc,
- LPRECT pos,
- LPARAM d) {
- moveToMonitorData* data = (moveToMonitorData*)d;
- MONITORINFOEXA info;
- memset(&info, 0, sizeof(info));
- info.cbSize = sizeof(info);
-
- if ((*_GetMonitorInfo)(monitor, &info)) {
- if (stricmp(data->monitorName, info.szDevice) == 0) {
- SetWindowPos(data->window, 0,
- info.rcMonitor.left, info.rcMonitor.top,
- info.rcMonitor.right, info.rcMonitor.bottom,
- SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
- return FALSE;
- }
- }
-
- return TRUE;
- }
-
- #endif
-
- void moveToMonitor(HWND handle, const char* device) {
- miLog.debug("moveToMonitor %s", device);
-
- #if (WINVER >= 0x500)
- typedef BOOL (WINAPI *_EnumDisplayMonitors_proto)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
- rfb::win32::DynamicFn<_EnumDisplayMonitors_proto> _EnumDisplayMonitors(_T("user32.dll"), "EnumDisplayMonitors");
- if (!_EnumDisplayMonitors.isValid()) {
- miLog.debug("EnumDisplayMonitors not found");
- return;
- }
-
- moveToMonitorData data;
- data.window = handle;
- data.monitorName = device;
-
- (*_EnumDisplayMonitors)(0, 0, &moveToMonitorEnumProc, (LPARAM)&data);
- #endif
- }
-
-
- void centerWindow(HWND handle, HWND parent, bool clipToParent) {
- RECT r;
- if (parent && IsWindowVisible(parent)) {
- if (!GetWindowRect(parent, &r)) return;
- } else {
- MonitorInfo mi(handle);
- r=mi.rcWork;
- }
- centerWindow(handle, r, clipToParent);
- }
-
- void centerWindow(HWND handle, const RECT& r, bool clipToRect) {
- RECT wr;
- if (!GetWindowRect(handle, &wr)) return;
- int w = wr.right-wr.left;
- int h = wr.bottom-wr.top;
- if (clipToRect) {
- w = min(r.right-r.left, w);
- h = min(r.bottom-r.top, h);
- }
- int x = (r.left + r.right - w)/2;
- int y = (r.top + r.bottom - h)/2;
- UINT flags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | (clipToRect ? 0 : SWP_NOSIZE);
- SetWindowPos(handle, 0, x, y, w, h, flags);
- }
-
-
- int MsgBox(HWND parent, const TCHAR* msg, UINT flags) {
- const TCHAR* msgType = 0;
- UINT tflags = flags & 0x70;
- if (tflags == MB_ICONHAND)
- msgType = _T("Error");
- else if (tflags == MB_ICONQUESTION)
- msgType = _T("Question");
- else if (tflags == MB_ICONEXCLAMATION)
- msgType = _T("Warning");
- else if (tflags == MB_ICONASTERISK)
- msgType = _T("Information");
- flags |= MB_TOPMOST | MB_SETFOREGROUND;
- int len = _tcslen(AppName.buf) + 1;
- if (msgType) len += _tcslen(msgType) + 3;
- TCharArray title = new TCHAR[len];
- _tcscpy(title.buf, AppName.buf);
- if (msgType) {
- _tcscat(title.buf, _T(" : "));
- _tcscat(title.buf, msgType);
- }
- return MessageBox(parent, msg, title.buf, flags);
- }
-
-
- };
- };
|