Страница 1 из 1

Win API функция

Добавлено: 01 янв 2012, 10:43
Slinger
С наступившим всех!

Буквально на прошедших днях возникла задача. Дописал утилиту для пакетной печати окон, осталось только реализовать выбор принтера для печати. Поскольку МапВасик не имеет функцию возвращения списка принтеров в системе, товарищ посоветовал использовать стандартную WinApi функцию, которая выполняет подобную операцию (стандартный раскрывающийся список с принтерами в окне печати). Она же кстати и используются в большинстве ПО. Собственно вопрос - как подключить подобную функцию, что и где надо добавлять? Поделитесь опытом, кто уже этим занимался.

Если что - MapBasic 7.8

Re: Win API функция

Добавлено: 01 янв 2012, 18:51
gamm
Slinger писал(а):товарищ посоветовал использовать стандартную WinApi функцию
найдите, в какой DLL системы находится функция, и импортируйте. Интерфейс описан в доках MS VS или MSDN
нашел тут следы экспериментов с DLL 15-летней давности, думаю, мало что изменилось ...

Код: Выделить всё

Include "с:\mapbasic\MAPBASIC.DEF"
Declare Sub dll_proc  Lib "с:\tmp\mb_dll.dll"  Alias "TESTMBDLL" (f As Float,i As Integer)
Call dll_proc(f,i)

Re: Win API функция

Добавлено: 01 янв 2012, 23:20
Slinger
Спасибо за наводку, однако созданием и подключением функций ни разу не занимался, может ли кто подсказать чуть подробнее на эту тему? В справочнике WinAPI нашёл функцию EnumPrinters (ссылка) с кучей аргументов. Что с ними делать и каким образом подключать?

Re: Win API функция

Добавлено: 03 янв 2012, 00:00
Aleksandr Dezhin
Если MapBasic это VBA, то проще наверное список принтеров через WMI получить, например как тут: http://technet.microsoft.com/en-us/libr ... 76746.aspx

Re: Win API функция

Добавлено: 10 янв 2012, 06:21
asgs
Slinger писал(а):Спасибо за наводку, однако созданием и подключением функций ни разу не занимался, может ли кто подсказать чуть подробнее на эту тему? В справочнике WinAPI нашёл функцию EnumPrinters (ссылка) с кучей аргументов. Что с ними делать и каким образом подключать?
Лично я бы в данном случае написал небольшую DLL на С++ с упрощенной функцией-оберткой для EnumPrinters, поскольку сильно уж много именованных констант используется в флагах, передавать их в MapBasic несколько затруднительно.
Пример подключения DLL в MapBasic можно посмотреть здесь: http://asgs.narod.ru/gplprog.html
Лучше в TiffMosaic.

Re: Win API функция

Добавлено: 13 янв 2012, 11:03
SergS
asgs писал(а):Лично я бы в данном случае написал небольшую DLL на С++ с упрощенной функцией-оберткой для EnumPrinters, поскольку сильно уж много именованных констант используется в флагах, передавать их в MapBasic несколько затруднительно.
Пример подключения DLL в MapBasic можно посмотреть здесь: http://asgs.narod.ru/gplprog.html
Лучше в TiffMosaic.
ну..., imho, в данном случае дело не в именованных константах (не так уж и много их здесь, да и работа с ними не сложная), а в "хитрой" организации данных в возвращаемом буфере и в тщательно скрываемом умении/неумении MB работать с указателями. С непривычки всю голову переломашь.
Пример получения списка установленных принтеров в MB (каюсь - без обработки ошибок):

Код: Выделить всё

include "mapbasic.def"

define PRINTER_ENUM_LOCAL &H00000002
define PRINTER_ENUM_CONNECTIONS &H00000004
define PRINTER_ENUM_NAME &H00000008

type PRINTER_INFO_1
  Flags as integer
  pDescription as string
  pName as string
  pComment as string
end type 

declare function EnumPrintersA Lib "winspool.drv" ( 
	byval Flags as integer, 
	byval Name as integer, 
	byval Level as integer, 
	buff() as integer, 
	byval cbBuf as integer,
	pcbNeeded as integer, 
	pcReturned  as integer
) as integer

declare function lstrlen Lib "kernel32" (byval c as integer) as integer
declare function lstrcpy Lib "kernel32" (s as string, byval buff as integer) as integer
declare sub PRINTER_INFO_1_convert( buff() as integer, pi() as PRINTER_INFO_1)

declare sub main()


sub main()
	CLS

	dim r as integer
	dim pi() as PRINTER_INFO_1
	dim ibuff() as integer
	dim i as integer
	dim pcbNeeded as integer
	dim pcReturned  as integer
	print "========================================================="
	r = EnumPrintersA(PRINTER_ENUM_CONNECTIONS+PRINTER_ENUM_LOCAL, 0, 1, ibuff, 0, pcbNeeded, pcReturned)
	print "размер буфера:" + str$(pcbNeeded) + " байт"
	redim ibuff(pcbNeeded/4)
	r = EnumPrintersA(PRINTER_ENUM_CONNECTIONS+PRINTER_ENUM_LOCAL, 0, 1, ibuff, pcbNeeded, pcbNeeded, pcReturned)
	print "количество структур PRINTER_INFO_1:" + str$(pcReturned)
	redim pi(pcReturned)
	call PRINTER_INFO_1_convert(ibuff, pi)
	print "Список установленных принтеров:"
	for i = 1 to pcReturned
		print str$(i) + ".------------------------------------------------"
		print pi(i).Flags
		print pi(i).pDescription
		print pi(i).pName
		print pi(i).pComment
	next
end sub

sub PRINTER_INFO_1_convert(buff() as integer, pi() as PRINTER_INFO_1)
	dim i, retv as integer
	for i = 1 to ubound(pi)
		pi(i).Flags = buff(4 * (i - 1) + 1)
		pi(i).pDescription = Space$( lstrlen ( buff(4 * (i - 1) + 2 ) ) )
		retv = lstrcpy( pi(i).pDescription, buff(4 * (i - 1) + 2))
		pi(i).pName = Space$( lstrlen ( buff(4 * (i - 1) + 3 ) ) )
		retv = lstrcpy( pi(i).pName , buff(4 * (i - 1) + 3))
		pi(i).pComment = Space$( lstrlen ( buff(4 * (i - 1) + 4 ) ) )
		retv = lstrcpy( pi(i).pComment, buff(4 * (i - 1) + 4))
	next
end sub
А теперь "НО"...
Опять же imho...
для поставленной задачи (выбор нужного принтера и, может быть, каких то его параметров) совсем не нужно так извращаться ( ведь придется еще и реализовать диалог выбора, а в случае установки еще каких то свойств для печати еще писать и писать...)
проще так (Вам ведь не нужен именно список - нужен ведь конкретный выбранный принтер):

Код: Выделить всё

Include "mapbasic.def"
Include "menu.def"

	dim p_name as string 'имя выбранного принтера
	dim hw as integer
	Layout  ' или Map, или Browser - вспомогательное "документальное" окно, Layout выбран потому, что его наполнять содержанием не обязательно
	hw = frontwindow()
	Run Menu Command M_FILE_PAGE_SETUP  ' стандартный в MI диалог установки параметров печати (и выбора принтера)
	' Сохраняем в переменных нужное:
	p_name = windowinfo(hw, WIN_INFO_PRINTER_NAME) ' имя принтера
	' для последующей установки с помощью оператора Set Window
	' ну и еще какие свойства - бумага, ориентация......

	close window hw ' теперь окно уже не нужно... 
ну и все, открываем в цикле-пакете нужные окна устанавливаем для них
Set Window .... (то что сохранили)
и печатаем

Re: Win API функция

Добавлено: 16 янв 2012, 07:44
asgs
Кстати да, второй вариант попроще будет в реализации, как мне кажется.

Re: Win API функция

Добавлено: 29 янв 2012, 23:04
Slinger
Всем спасибо за ответы, особенно SergS. Задача полностью решена.