#include "wxinc.h" #include "oswin32.h" #include "xvt_menu.h" #include "xvt_help.h" #define WIN32_LEAN_AND_MEAN #define WIN32_EXTRA_LEAN #define STRICT #include #include #include bool OsWin32_CheckPrinterInfo(const void* data, unsigned int size) { bool ok = data != NULL; if (ok) { LPDEVMODE pdm = (LPDEVMODE)data; const unsigned int s = pdm->dmSize + pdm->dmDriverExtra; ok = s > 0 && s == size; } return ok; } void* OsWin32_ConvertFromNativePrinterInfo(void* hGlobal, unsigned int& nDataSize) { void* ptr = ::GlobalLock(hGlobal); PDEVMODE dm = (PDEVMODE)ptr; nDataSize = dm->dmSize+dm->dmDriverExtra; void* buff = new char[nDataSize]; memcpy(buff, ptr, nDataSize); ::GlobalUnlock(hGlobal); return buff; } void* OsWin32_ConvertToNativePrinterInfo(void* data, unsigned int nDataSize) { HGLOBAL hGlobal = ::GlobalAlloc(GHND, nDataSize); void* ptr = ::GlobalLock(hGlobal); memcpy(ptr, data, nDataSize); ::GlobalUnlock(hGlobal); return hGlobal; } struct XvtData { char** families; long* sizes; short* scalable; long max_count; long cur_count; XvtData() { memset(this, 0, sizeof(XvtData)); } }; int CALLBACK FamilyEnumerator( const LOGFONT *plf, // pointer to logical-font data const TEXTMETRIC *lpntme, // pointer to physical-font data unsigned long FontType, // type of font LPARAM lParam // application-defined data ) { XvtData* d = (XvtData*)lParam; d->families[d->cur_count++] = strdup(plf->lfFaceName); return d->cur_count < d->max_count; } int CALLBACK SizeEnumerator( const LOGFONT *plf, // pointer to logical-font data const TEXTMETRIC *lpntme, // pointer to physical-font data unsigned long FontType, // type of font LPARAM lParam // application-defined data ) { XvtData* d = (XvtData*)lParam; long& i = d->cur_count; const int size = (plf->lfHeight+5) / 10; if (i == 0 || size > d->sizes[i-1]) { d->sizes[i] = size; if (lpntme->tmPitchAndFamily & TMPF_TRUETYPE) *d->scalable = TRUE; i++; } return i < d->max_count; } int FamilySorter(const void* p1,const void* p2) { const char* s1 = *(const char**)p1; const char* s2 = *(const char**)p2; return strcmp(s1, s2); } int OsWin32_EnumerateFamilies(unsigned int hDC, char** families, int max_count) { XvtData data; data.families = families; data.max_count = max_count; LOGFONT lf; memset(&lf, 0, sizeof(lf)); ::EnumFontFamiliesEx((HDC)hDC, &lf, FamilyEnumerator, (LPARAM)&data, 0); qsort(families, data.cur_count, sizeof(char*), FamilySorter); return data.cur_count; } int OsWin32_EnumerateSizes(unsigned int hDC, const char* name, long* sizes, short* scalable, int max_count) { XvtData data; data.sizes = sizes; data.scalable = scalable; data.max_count = max_count; LOGFONT lf; memset(&lf, 0, sizeof(lf)); strcpy(lf.lfFaceName, name); ::EnumFontFamiliesEx((HDC)hDC, &lf, SizeEnumerator, (LPARAM)&data, 0); return data.cur_count; } void* OsWin32_GetPrinterInfo(int& size, const char* printer) { char name[256]; size = 0; if (printer == NULL || *printer == '\0') { if (::GetProfileString("windows", "device", ",,,", name, sizeof(name)) == 0) return NULL; char* comma = strchr(name, ','); if (comma) *comma = '\0'; } else strcpy(name, printer); LPDEVMODE pdm = NULL; HANDLE hPrinter; if (::OpenPrinter(name, &hPrinter, NULL) != 0) { size = ::DocumentProperties(0, hPrinter, name, NULL, NULL, 0); // Determina dimensione DEVMODE if (size > 0) { pdm = (LPDEVMODE) new char[size]; // Alloca un DEVMODE sufficientemente capiente ::DocumentProperties(0, hPrinter, name, pdm, NULL, DM_OUT_BUFFER); // Legge DEVMODE } else size = 0; ::ClosePrinter(hPrinter); } return pdm; } void OsWin32_SetCaptionStyle(unsigned int handle, bool set) { HWND hwnd = (HWND)handle; DWORD s = ::GetWindowLong(hwnd, GWL_STYLE); if (set) s |= WS_CAPTION; else s &= ~WS_CAPTION; #if !wxCHECK_VERSION(2,3,2) s |= WS_CLIPSIBLINGS; #endif ::SetWindowLong(hwnd, GWL_STYLE, s); } void OsWin32_SetClippingRect(unsigned int hDC, int x, int y, int w, int h) { HDC hdc = (HDC)hDC; if (w > 0 && h > 0) { HRGN hrgn = ::CreateRectRgn(x, y, x+w, y+h); ::SelectClipRgn(hdc, hrgn); ::DeleteObject(hrgn); } else ::SelectClipRgn(hdc, NULL); } void OsWin32_UpdateWindow(unsigned int handle) { HWND hwnd = (HWND)handle; ::UpdateWindow(hwnd); } void OsWin32_StretchBlt(unsigned int hDst, int xd, int yd, int wd, int hd, unsigned int hSrc, int xs, int ys, int ws, int hs) { const int nColors = ::GetDeviceCaps((HDC)hDst, NUMCOLORS); ::SetStretchBltMode((HDC)hDst, nColors == 2 ? STRETCH_HALFTONE : STRETCH_DELETESCANS); ::StretchBlt((HDC)hDst, xd, yd, wd, hd, (HDC)hSrc, xs, ys, ws, hs, SRCCOPY); } /////////////////////////////////////////////////////////// // Drawing bitmaps /////////////////////////////////////////////////////////// void OsWin32_DrawBitmap(unsigned int hBitmap, unsigned int hDC, int xd, int yd, int wd, int hd, int xs, int ys, int ws, int hs) { const int nTechno = ::GetDeviceCaps((HDC)hDC, TECHNOLOGY); if (nTechno == DT_RASPRINTER) // Sto stampando! { BITMAPINFO bi; memset(&bi, 0, sizeof(bi)); BITMAPINFOHEADER& bih = bi.bmiHeader; bih.biSize = sizeof(bih); HDC hMemDC = ::CreateCompatibleDC(NULL); GetDIBits(hMemDC, (HBITMAP)hBitmap, 0, 0, NULL, &bi, DIB_RGB_COLORS); if (bih.biSizeImage > 0) { LPBYTE bits = new BYTE[bih.biSizeImage]; ::GetDIBits(hMemDC, (HBITMAP)hBitmap, 0, bih.biHeight, bits, &bi, DIB_RGB_COLORS); ::StretchDIBits((HDC)hDC, xd, yd, wd, hd, xs, ys, ws, hs, bits, &bi, DIB_RGB_COLORS, SRCCOPY); delete bits; } ::DeleteDC(hMemDC); } else { HDC hMemDC = ::CreateCompatibleDC((HDC)hDC); HGDIOBJ hOldBitmap = ::SelectObject(hMemDC, (HBITMAP)hBitmap); ::SetStretchBltMode((HDC)hDC, STRETCH_DELETESCANS); ::StretchBlt((HDC)hDC, xd, yd, wd, hd, hMemDC, xs, ys, ws, hs, SRCCOPY); ::SelectObject(hMemDC, hOldBitmap); ::DeleteDC(hMemDC); } } void OsWin32_DrawDottedRect(unsigned int hDC, int left, int top, int right, int bottom) { LOGBRUSH lBrush; lBrush.lbHatch = 0; lBrush.lbStyle = BS_SOLID; lBrush.lbColor = ::GetTextColor((HDC)hDC); HPEN hPen = ::ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lBrush, 0, NULL); HGDIOBJ hOldPen = ::SelectObject((HDC)hDC, hPen); HGDIOBJ hBrush = ::GetStockObject(HOLLOW_BRUSH); HGDIOBJ hOldBrush = ::SelectObject((HDC)hDC, hBrush); ::Rectangle((HDC)hDC, left, top, right, bottom); ::SelectObject((HDC)hDC, hOldBrush); ::SelectObject((HDC)hDC, hOldPen); ::DeleteObject(hPen); } void OsWin32_Beep(int severity) { switch (severity) { case 1: ::MessageBeep(MB_ICONEXCLAMATION); break; case 2: ::MessageBeep(MB_ICONSTOP); break; default: ::MessageBeep(MB_OK); break; } } int OsWin32_Help(unsigned int handle, const char* hlp, unsigned int cmd, const char* topic) { HWND hwnd = (HWND)handle; switch(cmd) { case M_HELP_CONTENTS: ::WinHelp(hwnd, hlp, HELP_CONTENTS, 0); break; case M_HELP_SEARCH: ::WinHelp(hwnd, hlp, HELP_PARTIALKEY, (DWORD)""); break; case M_HELP_HELPONHELP: ::WinHelp(hwnd, hlp, HELP_HELPONHELP, 0); break; case M_HELP_ONCONTEXT: if (topic != NULL) { struct MULTIGUY { DWORD mkSize; TCHAR mkKeylist; TCHAR mkKeyphrase[16]; } mk; mk.mkSize = sizeof(MULTIGUY); mk.mkKeylist = 'M'; strncpy(mk.mkKeyphrase, topic, sizeof(mk.mkKeyphrase)); ::WinHelp(hwnd, hlp, HELP_MULTIKEY, (DWORD)&mk); } break; default: ::WinHelp(hwnd, hlp, HELP_QUIT, 0); break; } return TRUE; } bool OsWin32_TestNetworkVersion() { // Win95 only! char* VREDIRNAME = "vredir.vxd"; DWORD handle; DWORD dwSize = ::GetFileVersionInfoSize(VREDIRNAME,&handle); if (dwSize) { BYTE infoBuffer[512]; GetFileVersionInfo(VREDIRNAME,handle,dwSize,infoBuffer); long *language; void * lpBuffer; UINT Size; if (VerQueryValue(infoBuffer, "\\VarFileInfo\\Translation", (void **)&language, &Size) && Size!=0) { char szName[128]; sprintf(szName, "\\StringFileInfo\\%04x%04x\\FileVersion",LOWORD(*language), HIWORD(*language)); if (VerQueryValue(infoBuffer, szName, &lpBuffer, &Size) && Size!=0) { const char* s = (const char *)lpBuffer; for (int i = 0; i < 2; i++) s = strchr(s, '.')+1; int subver=atoi(s); if (subver >= 1111 && subver <= 1115) return false; } } } return true; } /////////////////////////////////////////////////////////// // Execute in window support /////////////////////////////////////////////////////////// struct TFindWindowInfo { HINSTANCE _instance; wxString _file; HWND _hwnd; TFindWindowInfo() : _instance(NULL), _hwnd(NULL) { } }; BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { TFindWindowInfo* w = (TFindWindowInfo*)lParam; HINSTANCE inst = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE); if (inst == w->_instance) { const LONG style = GetWindowLong(hwnd, GWL_STYLE); if ((style & WS_CAPTION) != 0) // Ha la caption? { w->_hwnd = hwnd; return FALSE; } return TRUE; } char str[256]; GetWindowText(hwnd, str, sizeof(str)); wxString title = str; title.MakeUpper(); if (title.find(w->_file) >= 0) { w->_hwnd = hwnd; return FALSE; } return TRUE; } void OsWin32_PlaceProcessInWindow(unsigned int instance, const char* name, unsigned int parent) { TFindWindowInfo w; w._instance = (HINSTANCE)instance; w._file = name; w._file.MakeUpper(); for (int i = 0; w._hwnd == NULL && i < 20; i++) { wxThread::Sleep(500); ::EnumWindows(EnumWindowsProc, LPARAM(&w)); } if (w._hwnd != NULL) // L'ho trovata! { RECT rct; ::GetClientRect((HWND)parent, &rct); ::SetParent(w._hwnd, (HWND)parent); const int fx = ::GetSystemMetrics(SM_CXFRAME); const int fy = ::GetSystemMetrics(SM_CYFRAME); int cy = ::GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYBORDER); if (::GetMenu(w._hwnd) != NULL) cy += ::GetSystemMetrics(SM_CYMENU); ::SetWindowPos(w._hwnd, (HWND)parent, -fx, -fy-cy, rct.right+2*fx, rct.bottom+cy+2*fy, SWP_NOZORDER); } } /////////////////////////////////////////////////////////// // Ex-Golem utilities /////////////////////////////////////////////////////////// static long GetRegistryString(HKEY key, const char* subkey, wxString& retstr) { HKEY hkey; long retval = RegOpenKey(key, subkey, &hkey); if (retval == ERROR_SUCCESS) { char retdata[_MAX_PATH]; long datasize = sizeof(retdata); RegQueryValue(hkey, NULL, retdata, &datasize); RegCloseKey(hkey); retstr = retdata; } return retval; } wxString OsWin32_File2App(const char* filename) { wxString app; if (*filename != '.') { char retdata[_MAX_PATH]; HINSTANCE hinst = ::FindExecutable(filename, ".", retdata); DWORD* pinst = (DWORD*)hinst; UINT err = LOWORD(pinst); if (err > 32) app = retdata; } if (app.IsEmpty()) { char ext[_MAX_EXT]; if (*filename == '.') strcpy(ext, filename); else _splitpath(filename, NULL, NULL, NULL, ext); _strlwr(ext); wxString key; if (GetRegistryString(HKEY_CLASSES_ROOT, ext, key) == ERROR_SUCCESS) { key << "\\shell\\open\\command"; if (GetRegistryString(HKEY_CLASSES_ROOT, key, key) == ERROR_SUCCESS) { key.Replace("\"", " "); int pos = key.Find("%1"); if (pos > 0) key.Truncate(pos); key.Trim(false); key.Trim(true); app = key; } } } return app; } static bool IsInternetAddress(const char* filename) { const wxString url(filename); if (url.StartsWith("http:") || url.StartsWith("ftp:")) return TRUE; if (url.Find("www.") >= 0) return TRUE; char ext[_MAX_EXT]; _splitpath(filename, NULL, NULL, NULL, ext); _strlwr(ext); const char* const extensions[] = { "com","edu","gov","it","mil","net","org", NULL }; for (int e = 0; extensions[e]; e++) if (stricmp(ext, extensions[e]) == 0) return true; return false; } unsigned int OsWin32_LoadIcon(const char* filename) { unsigned int icon = 0; int icon_number = 0; char ext[_MAX_EXT]; if (*filename == '.' && strlen(filename) < _MAX_EXT) strcpy(ext, filename); else { if (IsInternetAddress(filename)) strcpy(ext, ".htm"); else _splitpath(filename, NULL, NULL, NULL, ext); } _strlwr(ext); wxString key; if (ext != ".exe") { if (GetRegistryString(HKEY_CLASSES_ROOT, ext, key) == ERROR_SUCCESS) { key << "\\DefaultIcon"; if (GetRegistryString(HKEY_CLASSES_ROOT, key, key) == ERROR_SUCCESS) // Windows 95 only { const int comma = key.find(','); if (comma > 0) { icon_number = atoi(key.Mid(comma+1)); key.Truncate(comma); } } else { key = OsWin32_File2App(filename); if (key.IsEmpty()) key = OsWin32_File2App(".htm"); } } } else key = filename; // Toglie eventuali parametri sulla riga si comando const int ext_pos = key.Find(".exe"); if (ext_pos > 0) key.Truncate(ext_pos+4); HINSTANCE hInst = NULL; HICON hicon = ::ExtractIcon(hInst, key, icon_number); if (hicon == NULL && icon_number != 0) hicon = ::ExtractIcon(hInst, key, 0); if (hicon != NULL) { DWORD dwicon = DWORD((DWORD*)hicon); icon = LOWORD(dwicon); } return icon; }