campo-sirio/xvaga/oswin32.cpp
guy 64c17343fb Patch level : 10.0 148
Files correlati     : xvaga.dll
Ricompilazione Demo : [ ]
Commento            :
0000934: impostazione nuova stampante
Se selezione file ed imposta stampante, se scelgo la stampante mi da l'errore che allego, se la stessa operazione si fa dal pc di Salomoni campo si chiude senza dare errori.


git-svn-id: svn://10.65.10.50/trunk@17536 c028cbd2-c16b-5b4b-a496-9718f37d4682
2008-11-03 11:39:49 +00:00

1038 lines
26 KiB
C++
Executable File

#include "wxinc.h"
#include "wx/filename.h"
#include "wx/image.h"
#include "wx/paper.h"
#include "oswin32.h"
#include "aclapi.h"
#include "xvt_menu.h"
#include "xvt_help.h"
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#define STRICT
#include <windows.h>
#include <winspool.h>
#include <shellapi.h>
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;
}
static int AdjustDevmodePlease(PDEVMODE dm)
{
// Forse dovremmo fare una Black List su file delle stampanti incompatibili):
// 1) "NRG SP 4100N PCL 5e"
// 2) aggiungere qui le altre
// Ma per ora zappiamo tutti i driver troppo grandi (> 3Kb)
if (dm->dmDriverExtra > 3*1024)
dm->dmDriverExtra = 0;
// Controllo il formato della carta
wxPrintPaperType* paper = wxThePrintPaperDatabase->FindPaperTypeByPlatformId(dm->dmPaperSize);
if (paper == NULL)
{
dm->dmFields |= DM_PAPERSIZE;
wxThePrintPaperDatabase->WXADDPAPER((wxPaperSize)dm->dmPaperSize /*wxPAPER_NONE*/, dm->dmPaperSize,
dm->dmFormName, dm->dmPaperWidth, dm->dmPaperLength);
}
return dm->dmSize + dm->dmDriverExtra;
}
void* OsWin32_ConvertFromNativePrinterInfo(void* hGlobal, unsigned int& nDataSize)
{
void* buff = NULL;
if (hGlobal != NULL)
{
PDEVMODE dm = (PDEVMODE)::GlobalLock(hGlobal);
nDataSize = AdjustDevmodePlease(dm);
buff = new char[nDataSize];
memcpy(buff, dm, nDataSize);
::GlobalUnlock(hGlobal);
}
return buff;
}
void* OsWin32_ConvertToNativePrinterInfo(void* data, unsigned int nDataSize)
{
HGLOBAL hGlobal = ::GlobalAlloc(GHND, nDataSize); // Alloco lo spazio necessario
if (hGlobal != NULL)
{
PDEVMODE dm = (PDEVMODE)::GlobalLock(hGlobal); // Trasformo l'handle in puntatore
memcpy(dm, data, nDataSize); // Ricopio i dati della stampante
const unsigned int sz = AdjustDevmodePlease(dm); // Metto a posto parametri non standard
wxASSERT(nDataSize == sz);
::GlobalUnlock(hGlobal); // Libero il lock sull'handle
}
return hGlobal;
}
struct XvtData
{
char** families;
long* sizes;
short* scalable;
int max_count;
int 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;
int& n = d->cur_count;
int i;
for (i = n-1; i >= 0 && wxStricmp(d->families[i], plf->lfFaceName); i--);
if (i < 0) // Controlla che il nome del font non ci sia gia'
d->families[n++] = _strdup(plf->lfFaceName);
return n < 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;
int& i = d->cur_count;
int size = (plf->lfHeight+5) / 10;
if (size <= 0)
{
for (const char* n = plf->lfFaceName; *n; n++)
if (*n >= '1' && *n <= '9')
{
size = int(120.0 / atoi(n) + 0.5);
break;
}
if (size <= 0)
size = 12;
}
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 wxStricmp(s1, s2);
}
int OsWin32_EnumerateFamilies(WXHDC hDC, char** families, int max_count)
{
XvtData data;
data.families = families;
data.max_count = max_count;
LOGFONT lf; memset(&lf, 0, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET;
::EnumFontFamiliesEx((HDC)hDC, &lf, FamilyEnumerator, (LPARAM)&data, 0);
qsort(families, data.cur_count, sizeof(char*), FamilySorter);
return data.cur_count;
}
int OsWin32_EnumerateSizes(WXHDC 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));
lf.lfCharSet = DEFAULT_CHARSET;
strcpy(lf.lfFaceName, name);
::EnumFontFamiliesEx((HDC)hDC, &lf, SizeEnumerator, (LPARAM)&data, 0);
return data.cur_count;
}
void* OsWin32_GetPrinterInfo(int& size, const char* printer)
{
LPDEVMODE pdm = NULL;
size = 0;
char name[_MAX_PATH];
if (printer == NULL || *printer == '\0')
{
if (::GetProfileString("windows", "device", ",,,", name, sizeof(name)) == 0)
return NULL;
char* comma = strchr(name, ',');
if (comma) *comma = '\0';
}
else
wxStrncpy(name, printer, sizeof(name));
HANDLE hPrinter = NULL;
if (::OpenPrinter(name, &hPrinter, NULL))
{
size = ::DocumentProperties(0, hPrinter, name, NULL, NULL, 0); // Determina dimensione DEVMODE
if (size > 0)
{
pdm = (LPDEVMODE)new BYTE[size]; // Alloca un DEVMODE sufficientemente capiente
memset(pdm, 0, size); // Azzera tutto per bene
::DocumentProperties(0, hPrinter, name, pdm, NULL, DM_OUT_BUFFER); // Legge DEVMODE
size = AdjustDevmodePlease(pdm);
}
else
size = 0;
::ClosePrinter(hPrinter);
}
return pdm;
}
void OsWin32_SetCaptionStyle(WXHWND handle, long style)
{
HWND hWnd = (HWND)handle;
LONG s = ::GetWindowLong(hWnd, GWL_STYLE);
if (style & wxSYSTEM_MENU)
s |= WS_CAPTION;
else
s &= ~WS_CAPTION;
if (style & wxCLOSE_BOX)
s |= WS_SYSMENU;
else
s &= ~WS_SYSMENU;
s |= WS_CLIPSIBLINGS; // Forzatura necessaria da wx261
::SetWindowLong(hWnd, GWL_STYLE, s);
if (style & wxCLOSE_BOX)
{
HMENU hMenu = ::GetSystemMenu(hWnd, FALSE);
::EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
HICON hIcon = ::ExtractIcon(NULL, "res/campo.ico", 0);
::SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
}
}
///////////////////////////////////////////////////////////
// Drawing bitmaps
///////////////////////////////////////////////////////////
HBITMAP OsWin32_CreateBitmap(const wxImage& img, wxDC& dc)
{
static wxPalette pal;
HDC hDC = (HDC)dc.GetHDC();
int nDepth = dc.GetDepth();
// Altrimenti le stampanti in B/N perdono i toni di grigio
if (nDepth == 1 && !OsWin32_IsWindowsServer())
{
hDC = NULL;
nDepth = 24;
}
if (nDepth == 8)
{
if (!pal.Ok())
{
unsigned char red[256], green[256], blue[256];
PALETTEENTRY pe[256]; memset(pe, 0, sizeof(pe));
UINT nEntries = ::GetSystemPaletteEntries(hDC, 0, 256, pe);
for (UINT i = 0; i < nEntries; i++)
{
red[i] = pe[i].peRed;
green[i] = pe[i].peGreen;
blue[i] = pe[i].peBlue;
}
pal.Create(nEntries, red, green, blue);
}
dc.SetPalette(pal);
}
const int nWidth = img.GetWidth();
const int nHeight = img.GetHeight();
int nBytesPerLine = 0;
int nPadding = 0;
int nBitCount = 24;
switch (nDepth)
{
case 32: // Better if > Win98 :-) too
nBitCount = 32;
nBytesPerLine = nWidth*4;
break;
default:
nBytesPerLine = nWidth*3;
break;
}
const int nResto = nBytesPerLine % 4;
if (nResto != 0)
{
nPadding = 4 - nResto;
nBytesPerLine += nPadding;
}
const int nImageSize = nHeight*nBytesPerLine;
// Create the DIB section
unsigned char* pbits = (unsigned char*)calloc(nImageSize, 1);
const size_t bi_size = sizeof(BITMAPINFOHEADER);
BITMAPINFO* bi = (BITMAPINFO*)calloc(bi_size, 1);
bi->bmiHeader.biSize = bi_size;
bi->bmiHeader.biWidth = nWidth;
bi->bmiHeader.biHeight = -nHeight;
bi->bmiHeader.biCompression = BI_RGB;
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = nBitCount;
bi->bmiHeader.biSizeImage = nImageSize;
switch (nBitCount)
{
case 24:
{
unsigned char* d = img.GetData();
unsigned char* p = pbits;
for (int y = 0; y < nHeight; y++)
{
for (int x = 0; x < nWidth; x++)
{
*(p++) = *(d+2);
*(p++) = *(d+1);
*(p++) = *(d+0);
d += 3;
}
for (int i = 0; i < nPadding; i++)
*(p++) = 0;
}
}
break;
case 32:
{
unsigned char* d = img.GetData();
unsigned char* p = pbits;
for (int y = 0; y < nHeight; y++)
{
for (int x = 0; x < nWidth; x++)
{
*(p++) = *(d+2);
*(p++) = *(d+1);
*(p++) = *(d+0);
*(p++) = 0;
d += 3;
}
}
}
break;
default:
break;
}
HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight);
if (hBitmap)
{
HDC memdc = ::CreateCompatibleDC( hDC );
HBITMAP hOldBitmap = (HBITMAP)::SelectObject( memdc, hBitmap);
HPALETTE hOldPalette = NULL;
if (nDepth == 8)
{
hOldPalette = ::SelectPalette(memdc, (HPALETTE)pal.GetHPALETTE(), FALSE);
::RealizePalette(memdc);
}
::StretchDIBits( memdc, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight, pbits, bi, DIB_RGB_COLORS, SRCCOPY);
if (hOldBitmap)
::SelectObject(memdc, hOldBitmap);
if (hOldPalette)
::SelectPalette(memdc, hOldPalette, FALSE);
::DeleteDC(memdc);
}
free(pbits);
free(bi);
return hBitmap;
}
bool OsWin32_DrawBitmap(HBITMAP hBMP, wxDC& dc, const wxRect& dst, const wxRect& src)
{
static wxPalette pal;
bool ok = hBMP != NULL;
if (ok)
{
HDC hDC = (HDC)dc.GetHDC();
const int nTechno = ::GetDeviceCaps(hDC, TECHNOLOGY);
HDC hMemDC = NULL;
if (OsWin32_IsWindowsServer())
hMemDC = ::CreateCompatibleDC(hDC); // Per Terminal Server devo fare cosi'
else
hMemDC = ::CreateCompatibleDC(NULL); // Per gli altri sistemi devo fare cosa'
BITMAP bmp; ::GetObject(hBMP, sizeof(bmp), &bmp);
if (nTechno == DT_RASPRINTER) // Sto stampando!
{
const size_t bi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
BITMAPINFO* bi = (BITMAPINFO*)calloc(bi_size, 1); // Alloca ed azzera
BITMAPINFOHEADER& bih = bi->bmiHeader;
bih.biSize = sizeof(bih);
GetDIBits(hMemDC, hBMP, 0, bmp.bmHeight, NULL, bi, DIB_RGB_COLORS);
ok = bih.biSizeImage > 0;
if (ok)
{
LPBYTE bits = new BYTE[bih.biSizeImage];
::GetDIBits(hMemDC, hBMP, 0, src.height, bits, bi, DIB_RGB_COLORS);
::StretchDIBits(hDC, dst.x, dst.y, dst.width, dst.height, src.x, src.y, src.width, src.height,
bits, bi, DIB_RGB_COLORS, SRCCOPY);
delete bits;
}
free(bi);
}
else
{
HGDIOBJ hOldBitmap = ::SelectObject(hMemDC, hBMP);
::SetStretchBltMode(hDC, HALFTONE);
::StretchBlt(hDC, dst.x, dst.y, dst.width, dst.height,
hMemDC, src.x, src.y, src.width, src.height, SRCCOPY);
::SelectObject(hMemDC, hOldBitmap);
}
::DeleteDC(hMemDC);
}
return ok;
}
void OsWin32_DrawDottedRect(WXHDC 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;
}
}
static wxString GetHelpDir()
{
return "htmlhelp/";
}
static wxString FindHelpFile(const char* topic)
{
wxString strTopic = topic;
wxString strApp;
wxFileName::SplitPath(wxTheApp->argv[0], NULL, &strApp, NULL);
if (strTopic.IsEmpty())
{
strTopic = strApp;
strTopic += "100a";
}
wxString str;
for (int i = 0; i < 2; i++)
{
str = GetHelpDir();
str += i == 0 ? strTopic.Left(2) : strApp.Left(2);
str += "/";
str += strTopic;
str += ".html";
if (wxFileExists(str))
break;
}
return str;
}
int OsWin32_Help(WXHWND handle, const char* hlp, unsigned int cmd, const char* topic)
{
HWND hwnd = (HWND)handle;
wxString str;
switch(cmd)
{
case M_HELP_ONCONTEXT:
str = FindHelpFile(topic);
break;
default:
str = GetHelpDir();
str += "index.html";
break;
}
if (!str.IsEmpty() && wxFileExists(str))
{
::ShellExecute(hwnd, "open", str, NULL, NULL, SW_SHOWDEFAULT);
return true;
}
OsWin32_Beep(1);
return false;
}
///////////////////////////////////////////////////////////
// Execute in window support
///////////////////////////////////////////////////////////
struct TFindWindowInfo
{
HINSTANCE _instance;
wxString _file;
HWND _hwnd;
TFindWindowInfo() : _instance(NULL), _hwnd(NULL) { }
};
static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
TFindWindowInfo* w = (TFindWindowInfo*)lParam;
if (w->_instance != NULL)
{
HINSTANCE inst = (HINSTANCE)::GetWindowLong(hwnd, GWL_HINSTANCE);
if (inst == w->_instance)
{
// Cerco di capire se e' la finetra principale dal fatto che
// abbia la caption ed i bottoni di chiusura
const DWORD dwWanted = WS_CAPTION | WS_SYSMENU;
const DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
if ((style & dwWanted) == dwWanted)
{
w->_hwnd = hwnd;
return FALSE;
}
return TRUE;
}
}
if (!w->_file.IsEmpty())
{
char str[_MAX_PATH];
if (::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++)
{
::wxMilliSleep(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);
}
}
static BOOL CALLBACK EnumCampoChildrenProc(HWND hwnd, LPARAM lParam)
{
char str[_MAX_PATH];
if (::GetWindowText(hwnd, str, sizeof(str)))
{
TFindWindowInfo* w = (TFindWindowInfo*)lParam;
if (w->_file == str)
{
w->_hwnd = hwnd;
return FALSE;
}
}
return TRUE;
}
static BOOL CALLBACK EnumCampoWindowsProc(HWND hwnd, LPARAM lParam)
{
char str[_MAX_PATH];
if (::GetWindowText(hwnd, str, sizeof(str)))
{
const wxString title = str;
if (title.StartsWith("Base - "))
{
::EnumChildWindows(hwnd, EnumCampoChildrenProc, lParam);
TFindWindowInfo* w = (TFindWindowInfo*)lParam;
if (w->_hwnd != NULL)
return FALSE;
}
}
return TRUE;
}
unsigned int OsWin32_FindMenuContainer()
{
TFindWindowInfo w;
w._file = "__CAMPO_HOST_WINDOW__";
::EnumWindows(EnumCampoWindowsProc, LPARAM(&w));
return (unsigned int)w._hwnd;
}
static BOOL CALLBACK CountChildrenProc(HWND hwnd, LPARAM lParam)
{
LONG* n = (LONG*)lParam;
(*n)++;
return TRUE;
}
long OsWin32_GetChildrenCount(unsigned int parent)
{
LONG n = 0;
::EnumChildWindows((HWND)parent, CountChildrenProc, (LPARAM)&n);
return n;
}
static BOOL CALLBACK CloseChildrenProc(HWND hwnd, LPARAM lParam)
{
::PostMessage(hwnd, WM_CLOSE, 0, 0);
return CountChildrenProc(hwnd, lParam);
}
long OsWin32_CloseChildren(unsigned int parent)
{
LONG n = 0;
::EnumChildWindows((HWND)parent, CloseChildrenProc, (LPARAM)&n);
return n;
}
///////////////////////////////////////////////////////////
// Hardlock Support
///////////////////////////////////////////////////////////
#include "hlapi_c.h"
bool OsWin32_HL_Login(unsigned short address, const unsigned char* label, const unsigned char* password)
{
int err = HL_LOGIN(address, LOCAL_DEVICE, (unsigned char*)label, (unsigned char*)password);
return err == STATUS_OK;
}
bool OsWin32_HL_Logout()
{
HL_LOGOUT();
return TRUE;
}
bool OsWin32_HL_Read(unsigned short reg, unsigned short* data)
{
int err = HL_READ(reg, data);
return err == STATUS_OK;
}
bool OsWin32_HL_ReadBlock(unsigned char* data)
{
int err = HL_READBL(data);
return err == STATUS_OK;
}
bool OsWin32_HL_Write(unsigned short reg, unsigned short data)
{
int err = HL_WRITE(reg, data);
return err == STATUS_OK;
}
bool OsWin32_HL_Crypt(unsigned short* data) // Array di 4 words (8 bytes)
{
int err = HL_CODE(data, 1);
return err == STATUS_OK;
}
///////////////////////////////////////////////////////////
// Eutron Smartlink Support
///////////////////////////////////////////////////////////
#include "skeylink.h"
static KEY_NET _eutron_key;
bool OsWin32_SL_Crypt(unsigned short* data)
{
_eutron_key.net_command = NET_KEY_ACCESS;
_eutron_key.command = SCRAMBLING_MODE;
memcpy(_eutron_key.data, data, 8);
smartlink(&_eutron_key);
if (_eutron_key.status == ST_OK)
memcpy(data, _eutron_key.data, 8);
return _eutron_key.status == ST_OK;
}
bool OsWin32_SL_Login(const unsigned char* label, const unsigned char* password)
{
memset(&_eutron_key, 0, sizeof(KEY_NET));
_eutron_key.net_command = NET_KEY_OPEN;
_eutron_key.status = ST_HW_FAILURE; // Don't leave ST_OK = 0 here!
memcpy(_eutron_key.label, label, strlen((const char*)label));
memcpy(_eutron_key.password, password, strlen((const char*)password));
smartlink(&_eutron_key);
return _eutron_key.status == ST_OK;
}
bool OsWin32_SL_Logout()
{
_eutron_key.net_command = NET_KEY_CLOSE;
_eutron_key.command = 0;
smartlink(&_eutron_key);
return true;
}
bool OsWin32_SL_ReadBlock(unsigned short reg, unsigned short size, unsigned short* data)
{
_eutron_key.net_command = NET_KEY_ACCESS;
_eutron_key.command = BLOCK_READING_MODE;
unsigned short* pointer = (unsigned short*)(&_eutron_key.data[0]);
unsigned short* number = (unsigned short*)(&_eutron_key.data[2]);
*pointer = reg;
*number = size;
smartlink(&_eutron_key);
bool ok = _eutron_key.status == ST_OK;
if (ok)
memcpy(data, &_eutron_key.data[4], size*sizeof(unsigned short));
return ok;
}
bool OsWin32_SL_WriteBlock(unsigned short reg, unsigned short size, const unsigned short* data)
{
_eutron_key.net_command = NET_KEY_ACCESS;
_eutron_key.command = BLOCK_WRITING_MODE;
unsigned short* pointer = (unsigned short*)(&_eutron_key.data[0]);
unsigned short* number = (unsigned short*)(&_eutron_key.data[2]);
*pointer = reg;
*number = size;
memcpy(&_eutron_key.data[4], data, size*sizeof(unsigned short));
smartlink(&_eutron_key);
return _eutron_key.status == ST_OK;
}
///////////////////////////////////////////////////////////
// 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())
{
wxString ext;
if (*filename == '.')
ext = filename;
else
wxSplitPath(filename, NULL, NULL, &ext);
ext.MakeLower();
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)
{
wxString url(filename); url.MakeLower();
if (url.StartsWith("http:") || url.StartsWith("ftp:"))
return true;
if (url.Find("www.") >= 0)
return true;
wxString ext; wxFileName::SplitPath(url, NULL, NULL, NULL, &ext);
const char* const extensions[] = { "com","edu","gov","it","mil","net","org", NULL };
for (int e = 0; extensions[e]; e++)
if (ext == extensions[e])
return true;
return false;
}
unsigned int OsWin32_LoadIcon(const char* filename)
{
unsigned int icon = 0;
int icon_number = 0;
wxString ext;
if (*filename == '.' && strlen(filename) < _MAX_EXT)
ext = filename;
else
{
if (IsInternetAddress(filename))
ext = ".htm";
else
wxFileName::SplitPath(filename, NULL, NULL, NULL, &ext);
}
ext.MakeLower();
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;
}
// action = [ open, edit, print ];
bool OsWin32_GotoUrl(const char* url, const char* action)
{
bool ok = false;
// Sarebbe meglio un flag esplicito, ma per ora attendiamo solo le stampe
if (action && strcmp(action, "print") == 0)
{
SHELLEXECUTEINFO sei; memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
sei.lpVerb = action;
sei.lpFile = url;
sei.nShow = SW_SHOWNORMAL;
if (::ShellExecuteEx(&sei))
{
if (sei.hProcess != NULL)
{
::WaitForSingleObject(sei.hProcess, 0);
::CloseHandle(sei.hProcess);
}
ok = true;
}
}
else
{
HINSTANCE hinst = ::ShellExecute(NULL, action, url, NULL, NULL, SW_SHOWNORMAL);
DWORD winst = DWORD((DWORD*)hinst); // Tutto 'sto giro per evitare un warning
ok = UINT(winst) > 32;
}
return ok;
}
void OsWin32_SpoolNewLine(unsigned int hdc)
{
char output[4];
output[0] = 1; // Lunghezza: byte basso
output[1] = 0; // Lunghezza: byte alto
output[2] = '\n'; // A capo
output[3] = 0; // Shwarzenegger
::Escape((HDC)hdc, PASSTHROUGH, 0, output, NULL );
}
bool OsWin32_IsGenericTextOnly(void* data)
{
LPDEVMODE pdm = (LPDEVMODE)data;
if (pdm->dmYResolution == 6) // Win 9x only
return true;
if (strstr((const char*)pdm->dmDeviceName, "eneric") != NULL)
return true;
return false;
}
#ifdef SPEECH_API
#include "\Programmi\Microsoft Speech SDK 5.1\Include\sapi.h"
static ISpVoice* m_pVoice = NULL;
bool OsWin32_InitializeSpeech()
{
if (m_pVoice == NULL)
CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&m_pVoice);
return m_pVoice != NULL;
}
void OsWin32_DeinitializeSpeech()
{
if (m_pVoice != NULL)
{
m_pVoice->WaitUntilDone(1000);
m_pVoice->Release();
m_pVoice = NULL;
}
}
bool OsWin32_Speak(const char* text, bool async)
{
if (m_pVoice != NULL)
{
WCHAR str[1204];
MultiByteToWideChar(CP_ACP, 0, text, -1, str, strlen(text)+1);
if (async)
m_pVoice->Speak(str, SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL);
else
m_pVoice->Speak(str, SPF_PURGEBEFORESPEAK, NULL);
return true;
}
return false;
}
#endif
typedef BOOL (PASCAL *pfnProcessIdToSessionId)(DWORD dwProcessId,DWORD* pSessionId);
int OsWin32_GetSessionId()
{
DWORD session = 0;
#if _MSC_VER >= 1300
//modifiche del 1/2/08 per poter gestire le licenze con win2000/2003/2008 server edition
::ProcessIdToSessionId(GetCurrentProcessId(), &session);
#else
//modifiche del 5/4/04 per poter gestire le licenze con win2000/2003 server edition
HMODULE kernel = GetModuleHandle("kernel32.dll");
if (kernel != NULL)
{
pfnProcessIdToSessionId fn = (pfnProcessIdToSessionId)GetProcAddress(kernel, "ProcessIdToSessionId");
if (fn != NULL)
fn(GetCurrentProcessId(), &session);
}
#endif
return (int)session;
}
//definito il valore della variabile intera SM_REMOTESESSION
// che non esiste per WINVER < 0x500
#ifndef SM_REMOTESESSION
#define SM_REMOTESESSION 0x1000
#endif
bool OsWin32_IsWindowsServer()
{
return ::GetSystemMetrics(SM_REMOTESESSION) != 0;
}
void OsWin32_NumberFormat(char* str, int size)
{
char buf[80];
::GetNumberFormat(LOCALE_USER_DEFAULT, 0, str, NULL, buf, sizeof(buf));
wxStrncpy(str, buf, size);
}