2011-09-16 17 views
1

これまでのところ、私は信じているwxPythonのユーザーインタフェースからプリンタからDevModeの同等のバージョンであるかをアクセスするには2つの異なる方法発見しました:の保存/復元プリンタDevModes - wxPythonを/ win32print

window = wx.GetTopLevelWindows()[0].GetHandle() 
name = self.itemMap['device'].GetValue() # returns a valid printer name. 
handle = win32print.OpenPrinter(name) 
dmin = None 
dmout = pywintypes.DEVMODEType() 
mode = DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT 

res = win32print.DocumentProperties(window, handle, name, dmout, dmin, mode) 

if res == 1: 
    print dmout.DriverData 

とも

これらのバイナリ構造には、デバイスの出力動作を制御するために必要な情報が含まれているように見えます。これは、保存されたdevmodeデータでPrintSetupダイアログをリロードするために直接使用することはできません。最初のケースでは、PyDEVMODEオブジェクトには、手動で設定する必要のある数十の個別のプロパティが含まれています(PyDEVMODE Reference)。 2番目のケースでは、いくつかのプロパティを制御するいくつかのGetter/Setterメソッドがありますが、すべてではありません(wxPrintData Reference)。実際のDevMode(バイナリデータ)からPython Devmodeオブジェクトを作成する方法を知っている人はいますか(どちらの方法でも、その違いは簡単です)?毎回正しい状態でダイアログを再オープンするために、個々の属性を手動で保存/リセットする必要はありません。

答えて

0

この時点で、これをPythonで直接実現するためのエレガントな方法はないようです。私が思いつくことができる最も近いのは、私が呼び出せるC++で書かれたdllでした。私は、完全なバイナリDevMode構造で終わり、そこからリロードすることができます。そのC++のdllのコードは次のようになります。

Pythonで
#include "stdafx.h" 
#include <iobind/base64_policy.hpp> 

#include <string> 
#ifdef _UNICODE 
    typedef std::wstring string_t; 
#else 
    typedef std::string string_t; 
#endif 
typedef std::string cstring; 


extern "C" BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { 
    switch (dwReason){ 
     case DLL_PROCESS_ATTACH: 
      DisableThreadLibraryCalls(hModule); 
      break; 
     case DLL_PROCESS_DETACH: 
      break; 
    } 

    return TRUE; 
} 


extern "C" DOEXPORT int CleanupA(char *output) { 
    if (output) { 
     free(output); 
     output = NULL; 
    } 
    return 0; 
} 


extern "C" DOEXPORT int CleanupW(wchar_t *output) { 
    if (output) { 
     free(output); 
     output = NULL; 
    } 
    return 0; 
} 


extern "C" DOEXPORT int printer_setup( 
     void *handle, const TCHAR *printer_in, const char *input, 
     int local_only, TCHAR **printer, char **output) 
{ 
    HWND hwnd = (HWND)handle; 
    HRESULT hResult = 0; 

    LPPRINTDLG pPD = NULL; 
    LPPRINTPAGERANGE pPageRanges = NULL; 

    // Allocate structure. 
    pPD = (LPPRINTDLG)GlobalAlloc(GPTR, sizeof(PRINTDLG)); 
    if (!pPD) return E_OUTOFMEMORY; 

    // Initialize structure. 
    pPD->lStructSize = sizeof(PRINTDLG); 
    pPD->hwndOwner = hwnd; 

    pPD->hDevMode = NULL; 
    if (input){ 
     std::string dec = iobind::encode(input, iobind::from_base64_p); 
     if (!dec.empty()) { 
      HGLOBAL devmode = pPD->hDevMode = ::GlobalAlloc(GPTR, dec.size()); 
      if (devmode){   
       LPDEVMODE src = (LPDEVMODE)&dec[0]; 
       memcpy(devmode, src, dec.size()); 
      } 
     } 
    } 

    pPD->hDevNames = NULL; 
    if (printer_in){ 
     HGLOBAL printer = pPD->hDevNames = ::GlobalAlloc(GPTR, sizeof(DEVNAMES)+_tcslen(printer_in)*sizeof(TCHAR)+sizeof(TCHAR)); 
     if (printer){ 
      LPDEVNAMES dv = (LPDEVNAMES)printer; 
      dv->wDefault = 0; 
      dv->wDriverOffset = 0; 
      dv->wOutputOffset = 0; 
      dv->wDeviceOffset = sizeof(DEVNAMES)/sizeof(TCHAR); 
      TCHAR *dest = (TCHAR *)(unsigned long)dv + dv->wDeviceOffset; 
      _tcscpy(dest, printer_in); 
     } 
    } 

    pPD->hDC = NULL; 
    pPD->Flags = PD_PRINTSETUP; 

    if (local_only) { 
     pPD->Flags |= /*PD_ENABLESETUPHOOK |*/ PD_NONETWORKBUTTON; 
     //pPD->lpfnSetupHook = SetupHookProc; //removed: doing things differently, don't like how this was working 
    } 

    pPD->nMinPage = 1; 
    pPD->nMaxPage = 1000; 
    pPD->nCopies = 1; 
    pPD->hInstance = 0; 
    pPD->lpPrintTemplateName = NULL; 

    // Invoke the Print property sheet. 
    hResult = PrintDlg(pPD); 
    if (hResult != 0) { 
     if (pPD->hDevMode) { 
      LPDEVMODE devmode = (LPDEVMODE)::GlobalLock(pPD->hDevMode); 
      size_t size = devmode->dmSize + devmode->dmDriverExtra; 
      if (output) { 
       std::string tmp; 
       tmp.resize(size); 
       memcpy(&tmp[0], devmode, tmp.size()); 

       std::string enc = iobind::encode(tmp, iobind::to_base64_p); 
       *output = _strdup(enc.c_str()); 
      } 
      ::GlobalUnlock(pPD->hDevMode); 
     } 

     if (pPD->hDevNames) { 
      LPDEVNAMES devnames = (LPDEVNAMES)::GlobalLock(pPD->hDevNames); 
      TCHAR *device = (TCHAR *)(unsigned long)devnames + devnames->wDeviceOffset; 
      *printer = _tcsdup(device); 
      ::GlobalUnlock(pPD->hDevNames); 
     } 
    } 
    else { 
     DWORD dlgerr = ::CommDlgExtendedError(); 
     hResult = dlgerr; 
    } 

    if (pPD->hDC != NULL) { 
     DeleteDC(pPD->hDC); 
    } 
    if (pPD->hDevMode != NULL) { 
     GlobalFree(pPD->hDevMode); 
    } 
    if (pPD->hDevNames != NULL) { 
     GlobalFree(pPD->hDevNames); 
    } 
    return hResult; 
} 

、それはそうのように呼ばれています:

client = ctypes.cdll.LoadLibrary(os.path.join(myDir, 'rpmclient.dll')) 
client.printer_setup.argtypes = [ctypes.c_void_p, 
           ctypes.c_wchar_p, 
           ctypes.c_char_p, 
           ctypes.c_int32, 
           ctypes.POINTER(ctypes.c_wchar_p), 
           ctypes.POINTER(ctypes.c_char_p)] 

client.printer_setup.restype = ctypes.c_int32 
client.CleanupA.argtypes = [ctypes.c_char_p] 
client.CleanupA.restype = ctypes.c_int32 
client.CleanupW.argtypes = [ctypes.c_wchar_p] 
client.CleanupW.restype = ctypes.c_int32 

p_in = ctypes.c_wchar_p(self.itemMap['device'].GetValue()) 
p_out = ctypes.c_wchar_p() 

d_in = ctypes.c_char_p(getattr(self, 'devmode', '')) 
d_out = ctypes.c_char_p() 

res = client.printer_setup(self.GetHandle(), 
          p_in, 
          d_in, 
          False, 
          p_out, 
          d_out) 

if res == 0: 
    return 

if res > 1: 
    # Error display code here. 

    return 

self.devmode = d_out.value 
関連する問題