[C++ WinApi] Wyświetlenie listy drukarek i portów

0

Hej!
Jak poprawnie wyświetlić w C++ (WinAPI lub VCL) liste drukarek i port do której jest podpięta drukarka ?
Próbowałem coś takiego,ale nie działa :

*HDC hdcDrukarki;
PRINTER_INFO_5 *pinfo;
DWORD dwRozmiarbuf, dwIloscdrukarek;
EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, NULL, 0, &dwRozmiarbuf, &dwIloscdrukarek);
pinfo = (PRINTER_INFO_5 *) malloc(dwRozmiarbuf);
EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, (PBYTE) pinfo, dwRozmiarbuf, &dwRozmiarbuf, &dwIloscdrukarek);
hdcDrukarki=CreateDC(NULL, NULL, pinfo->pPrinterName, NULL);

// pierwsza drukarka
MessageBox(NULL, pinfo[0].pPrinterName, "Komunikat", MB_ICONINFORMATION);
// druga drukarka itp (mozna to tez zrobic w petli)
MessageBox(NULL, pinfo[1].pPrinterName, "Komunikat", MB_ICONINFORMATION);

free(pinfo); 
0
LOSMARCELOS napisał(a)
*HDC hdcDrukarki;       --- raczej HDC*
...
DWORD dwRozmiarbuf, dwIloscdrukarek;   -- to trzeba wyzerowac przed wywolaniem funkcji ponizej
...
pinfo = (PRINTER_INFO_5 *) malloc(dwRozmiarbuf); --jestesmy w c++.. new PRINTER_INFO_5[dwIloscDrukarek]
...
// pierwsza drukarka
MessageBox(NULL, pinfo[0].pPrinterName, "Komunikat", MB_ICONINFORMATION);
// druga drukarka itp (mozna to tez zrobic w petli)
MessageBox(NULL, pinfo[1].pPrinterName, "Komunikat", MB_ICONINFORMATION);

free(pinfo); -- delete[] pinfo

a tak w ogole, moze poza 'nie dziala' to tak cos wiecej opisz co sie dzieje a co powinno?

0

A moze chodzi bardziej o PRINTER_ENUM_LOCAL? PRINTER_ENUM_DEFAULT powoduje pobranie informacji o drukarce domyslnej, ktora, o ile sie orientuje, moze byc tylko jedna...

A poza tym

MSDN napisał(a)

PRINTER_ENUM_DEFAULT Windows 95/98/Me: The function returns information about the default printer.

i to moze wiele wyjasniac...

0
johny_bravo napisał(a)

A moze chodzi bardziej o PRINTER_ENUM_LOCAL? PRINTER_ENUM_DEFAULT powoduje pobranie informacji o drukarce domyslnej, ktora, o ile sie orientuje, moze byc tylko jedna...

A poza tym

MSDN napisał(a)

PRINTER_ENUM_DEFAULT Windows 95/98/Me: The function returns information about the default printer.

i to moze wiele wyjasniac...

Hmmm ja używam Windows Vista,albo XP...
Chodzi o to,że ciągle zwracana jest wartość NULL

0

No rzecz w tym wlasnie, ze PRINTER_ENUM_DEFAULT zdaje sie nie dzialac na innych systemach niz wypisane. Probowales zmieniac na to co zasugerowalem? I co zwraca nulla?

0
johny_bravo napisał(a)

No rzecz w tym wlasnie, ze PRINTER_ENUM_DEFAULT zdaje sie nie dzialac na innych systemach niz wypisane. Probowales zmieniac na to co zasugerowalem? I co zwraca nulla?

Zmieniłem na PRINTER_ENUM_LOCAL...
Ok, działa,pokazuje lokalne drukarki... Tylko jak zrobić zeby pokazał sieciowe?

// wyświetlenie nazwy drukarki domyślnej
HDC hdcDrukarki;
PRINTER_INFO_5 *pinfo;
DWORD dwRozmiarbuf, dwIloscDrukarek;
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &dwRozmiarbuf, &dwIloscDrukarek);
pinfo = (PRINTER_INFO_5 *) malloc(dwRozmiarbuf);
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, (PBYTE) pinfo, dwRozmiarbuf, &dwRozmiarbuf, &dwIloscDrukarek);
hdcDrukarki=CreateDC(NULL, NULL, pinfo->pPrinterName, NULL);

int i = 0;
for (i = 0; i < dwIloscDrukarek; i++)
{
 MessageBox(NULL, pinfo[i].pPrinterName, "Komunikat", MB_ICONINFORMATION);
}

free(pinfo);

Może użyć PRINTER_ENUM_NETWORK (Windows NT/2000/XP: The function enumerates network printers in the computer's domain. This value is valid only if Level is 1. )
albo
PRINTER_ENUM_NAME (The function enumerates the printer identified by Name. This can be a server, a domain, or a print provider. If Name is NULL, the function enumerates available print providers. )
Ehh ale chodzi o to żeby program działał też na Win98/Me, a nie tylko na NT/2000/XP...

0

Sprobuj wyszukac po Name dajac np. * Moze wtedy przeszuka wszystkie? Do tego skoro to flagi to daj PRINTER_ENUM_LOCAL | PRINTER_ENUM_NETWORK - powinien wyszukac wszystkie. W Win98/ME uzyje i tak tej pierwszej z powodow podanych w dokumentacji, w innych systemach uzyje obu.

0
johny_bravo napisał(a)

Sprobuj wyszukac po Name dajac np. * Moze wtedy przeszuka wszystkie? Do tego skoro to flagi to daj PRINTER_ENUM_LOCAL | PRINTER_ENUM_NETWORK - powinien wyszukac wszystkie. W Win98/ME uzyje i tak tej pierwszej z powodow podanych w dokumentacji, w innych systemach uzyje obu.

EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_NETWORK, NULL, 2, NULL, 0, &dwRozmiarbuf, &dwIloscDrukarek);

Nic to nie zmienia... Spróbowałem dać || zamiast |

EnumPrinters(PRINTER_ENUM_LOCAL || PRINTER_ENUM_NETWORK, NULL, 2, NULL, 0, &dwRozmiarbuf, &dwIloscDrukarek);

Wtedy pokazuje się błąd krytyczny
First chance exception at $7762B09E. Exception class EAccessViolation with message 'Access violation at address 77B8631B in module 'ntdll.dll'. Read of address 00000009'. Process sysinfow.exe (5600)
A debbuger pokazuje :


{ tell the debugger about the raise of a non-Delphi exception }
{$IFNDEF LINUX}
procedure       NotifyNonDelphiException;
asm
        CMP     BYTE PTR DebugHook,0
        JE      @@1
        PUSH    EAX
        PUSH    EAX
        PUSH    EDX
        PUSH    ESP
        PUSH    2
        PUSH    cContinuable
        PUSH    cNonDelphiException
        CALL    RaiseExceptionProc
        ADD     ESP,8
        POP     EAX
@@1:
end;
0
LOSMARCELOS napisał(a)

Ok, działa,pokazuje lokalne drukarki... Tylko jak zrobić zeby pokazał sieciowe?

// wyświetlenie nazwy drukarki domyślnej
HDC hdcDrukarki;
PRINTER_INFO_5 *pinfo;
DWORD dwRozmiarbuf, dwIloscDrukarek;
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &dwRozmiarbuf, &dwIloscDrukarek);
pinfo = (PRINTER_INFO_5 *) malloc(dwRozmiarbuf);
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, (PBYTE) pinfo, dwRozmiarbuf, &dwRozmiarbuf, &dwIloscDrukarek);
hdcDrukarki=CreateDC(NULL, NULL, pinfo->pPrinterName, NULL);

int i = 0;
for (i = 0; i < dwIloscDrukarek; i++)
{
 MessageBox(NULL, pinfo[i].pPrinterName, "Komunikat", MB_ICONINFORMATION);
}

free(pinfo);

U mnie wyświetla sieciowe drukarki na WinXP i Win98 ;)

Dla flagi PRINTER_ENUM_LOCAL masz napisane, że:

Windows 95/98/Me: The function will also enumerate network printers because they are handled by the local print provider.

0

No to daj LOCAL jak pisze 0x666, to bedzie win98 zaklepane, a pozniej osobno NETWORK, zeby na XP i innych tez zobaczyc sieciowe.

0
johny_bravo napisał(a)

No to daj LOCAL jak pisze 0x666, to bedzie win98 zaklepane, a pozniej osobno NETWORK, zeby na XP i innych tez zobaczyc sieciowe.

Ale jak osobno ? Tzn napisać osobną procedure do XP? która wykrywa wersje systemu i jak jest 2000/xp to jako 1 parametr w EnumPrinters bedzie PRINTER_ENUM_NETWORK ??
A moze miec to jakies znaczenie,ze mam Windows Vista??? Dodam, środowisko w którym pisze program to Turbo C++

0

Nie, bez wykrywania. Wykonujesz powyzszy kod tylko dla LOCAL - czyli masz zalatwione wszystkie drukarki w systemach Win98/Me oraz drukarki lokalne dla reszty. Nastepnie ten sam kod (oczywiscie nie doslownie, to moze byc funkcja ;) ) dla NETWORK - czyli masz zalatwione sieciowe dla pozostalych systemow. Dla Win98/Me wynik powinien byc zaden, bo tak mowi dokumentacja.

W efekcie dostajesz wszystkie drukarki dla wszystkich obslugiwanych systemow.

0

Hmmm coś takiego spróbowałem :

HDC hdcDrukarki;
PRINTER_INFO_5 *pinfo;
DWORD dwRozmiarbuf, dwIloscDrukarek;
EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 5, NULL, 0, &dwRozmiarbuf, &dwIloscDrukarek);
pinfo = (PRINTER_INFO_5 *) malloc(dwRozmiarbuf);
EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 5, (PBYTE) pinfo, dwRozmiarbuf, &dwRozmiarbuf, &dwIloscDrukarek);
hdcDrukarki=CreateDC(NULL, NULL, pinfo->pPrinterName, NULL);

int i = 0;
for (i = 0; i < dwIloscDrukarek; i++)
{
 MessageBox(NULL, pinfo[i].pPrinterName, "Komunikat", MB_ICONINFORMATION);
}

free(pinfo);

Na Windows Vista działa...Jutro sprawdzę na Windows XP i Windows 98...

Chodzi o to, że program ma działać na Win98/Me/2000/Xp/Vista...

W dokumentacji WinAPI jest napisane :

When Name is NULL, setting Flags to PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS enumerates printers that are installed on the local machine. These printers include those that are physically attached to the local machine as well as remote printers to which it has a network connection.

Kurcze zamotane troszkę to Windows API...
No ale zawsze łatwiej z WinAPI korzystać niż np assemblera :-)

0

A rzeczywiscie, nie zauwazylem tego. Oby poszlo na 98, bo na XP powinno ;)

0

U mnie działa (win98 i winXP). Efekt identyczny jak z samym LOCAL.

0

Sprawdziłem na Win98 Second Edition.
Działa, ale dla pewności sprawdze jutro na innym z win 98....

1 użytkowników online, w tym zalogowanych: 0, gości: 1