DeviceCapabilities und DC_PAPERNAMES



  • Moin moin Community,

    Ich habe seit langem mal wieder ein Problem, welches ich selbst nicht gelöst bekomme.

    Bin zur Zeit dabei, einen eigenen Druckdialog zu konstruieren, da der Standard-Dialog bei weitem nicht ausreicht. Dafür möchte ich nun die durch den Drucker unterstützten Papierformate in eine ComboBox via eigener Funktion packen. Die Ermittlung der Namensliste über DeviceCapabilities stellt soweit erstmal kein Problem dar. Schwierig wird es für mich nur, die genauen Namen da dann rauszulesen. Gemäß MSDN belegt jeder Name der Papierformate im String 64 Zeichen und ist null-terminiert. Durch den ersten Aufruf von DeviceCapabilities ist mir die Anzahl der Papierformate an sich ja auch bekannt, so dass ein sukzessives Durchgehen der Namensliste und anschließendes Einfügen in die ComboBox unproblematisch sein sollte. Jedoch bekomme ich beim Aufruf in meiner ComboBox nur wenige Klarnamen, oft ist es ein Zeichenwirrwarr.

    Hier erstmal der Code:

    int EnumeratePaperNames (HWND combobox, wchar_t *str_printerName, wchar_t *str_printerPort)
    {
    	int epserr = EPSERR_NOERROR;
    	long retValue = 0;
    
    	int numPaperNames = DeviceCapabilities (str_printerName, str_printerPort, DC_PAPERNAMES, NULL, NULL);
    
    	wchar_t *str_paperNames;
    	str_paperNames = (wchar_t*) calloc (64 * numPaperNames, sizeof (wchar_t));
    
    	DeviceCapabilities (str_printerName, str_printerPort, DC_PAPERNAMES, str_paperNames, NULL);
    
    	wchar_t str_currentName[64];
    
    	int offset = 0;
    	for (int i = 0; i < numPaperNames; i++)
    	{
    		offset = ((64 * sizeof (wchar_t)) * i);
    		memcpy (str_currentName, str_paperNames + offset, 64 * sizeof (wchar_t));
    
    		retValue = SendMessage (combobox, CB_ADDSTRING, (WPARAM) 0, (LPARAM) str_currentName);
    		if (retValue == CB_ERR || retValue == CB_ERRSPACE)
    			epserr = EPSERR_FAILEDTOLISTPAPERS;
    
    		memset (str_currentName, '\0', 64);
    		retValue = 0;
    		offset = 0;
    	}
    
    	free (str_paperNames);
    
    	return epserr;
    }
    

    Ich nehme an, dass der Fehler bei memcpy liegt, allerdings finde ich keine Lösung. http://support.microsoft.com/kb/229718 hat mir auch nicht geholfen, da der Ansatz einer extra Funktion zum splitten der Namensliste auch nicht klappte. Hier auch einmal die Ausgabe der Funktion http://s29.postimg.org/q2vnpvd5j/formats.jpg.

    Hoffe ihr könnt mir einmal mehr helfen.

    Genießt das neue Jahr!



  • Fake oder Echt schrieb:

    Ich nehme an, dass der Fehler bei memcpy liegt ...

    Der Fehler steckt in 'offset = ((64 * sizeof (wchar_t)) * i);'. str_paperNames ist bereits ein wchar_t* 😉

    ...
        wchar_t str_currentName[64+1]; // 64 + '\0'
        str_currentName[64] = L'\0';
    
        for (int i = 0; i < numPaperNames; i++)
        {
            memcpy (str_currentName, str_paperNames + (i * 64), 64 * sizeof (wchar_t));
    
            retValue = SendMessage (combobox, CB_ADDSTRING, (WPARAM) 0, (LPARAM) str_currentName);
            if (retValue == CB_ERR || retValue == CB_ERRSPACE)
                epserr = EPSERR_FAILEDTOLISTPAPERS;
        }
    ...
    

    Frohes neues Jahr - osdt



  • Ich sehe also nur Bäume und keinen Wald. Funktioniert jetzt einwandfrei, vielen Dank!
    Und das mit dem zusätzlichen null-Zeichen ist auch eine nette Verbesserung (zumal ich das beim offset ja berücksichtigt hatte ... wohl wieder nur ein Baum unter vielen).

    Also doppelten Dank, und nochmals frohes neues Jahr!



  • Oder noch einfacher so.

    struct PaperName { wchar_t mPaperName[64]; };
    
      std::vector<std::wstring> paperNamesVector;
      int numPaperNames = ::DeviceCapabilities(printerName.c_str(), portName.c_str(), DC_PAPERS, NULL, NULL);
      if (numPaperNames > 0)
      {
        paperNamesVector.resize(numPaperNames);
        PaperName * paperNamesBuffer = new PaperName[numPaperNames];
        DeviceCapabilities(printerName.c_str(), portName.c_str(), DC_PAPERNAMES, (LPTSTR)paperNamesBuffer, NULL);
        for (int i = 0; i < numPaperNames; i++)
          paperNamesVector[i] = paperNamesBuffer[i].mPaperName;
        delete[] paperNamesBuffer;
      }
    

Anmelden zum Antworten