Win API функция

MapInfo, MapBasic
Ответить
Slinger
Гуру
Сообщения: 879
Зарегистрирован: 17 июн 2010, 23:14
Репутация: 207
Откуда: Москва

Win API функция

Сообщение Slinger » 01 янв 2012, 10:43

С наступившим всех!

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

Если что - MapBasic 7.8

gamm
Гуру
Сообщения: 4168
Зарегистрирован: 15 окт 2010, 08:33
Репутация: 1107
Ваше звание: программист
Откуда: Казань

Re: Win API функция

Сообщение gamm » 01 янв 2012, 18:51

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)

Slinger
Гуру
Сообщения: 879
Зарегистрирован: 17 июн 2010, 23:14
Репутация: 207
Откуда: Москва

Re: Win API функция

Сообщение Slinger » 01 янв 2012, 23:20

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

Аватара пользователя
Aleksandr Dezhin
Активный участник
Сообщения: 244
Зарегистрирован: 03 фев 2010, 10:47
Репутация: 14
Откуда: Москва

Re: Win API функция

Сообщение Aleksandr Dezhin » 03 янв 2012, 00:00

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

Аватара пользователя
asgs
Участник
Сообщения: 89
Зарегистрирован: 04 авг 2010, 06:35
Репутация: 1
Контактная информация:

Re: Win API функция

Сообщение asgs » 10 янв 2012, 06:21

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

SergS
Активный участник
Сообщения: 120
Зарегистрирован: 14 апр 2011, 13:24
Репутация: 5
Откуда: Екатеринбург

Re: Win API функция

Сообщение SergS » 13 янв 2012, 11:03

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 .... (то что сохранили)
и печатаем

Аватара пользователя
asgs
Участник
Сообщения: 89
Зарегистрирован: 04 авг 2010, 06:35
Репутация: 1
Контактная информация:

Re: Win API функция

Сообщение asgs » 16 янв 2012, 07:44

Кстати да, второй вариант попроще будет в реализации, как мне кажется.
Злобный йожег

Slinger
Гуру
Сообщения: 879
Зарегистрирован: 17 июн 2010, 23:14
Репутация: 207
Откуда: Москва

Re: Win API функция

Сообщение Slinger » 29 янв 2012, 23:04

Всем спасибо за ответы, особенно SergS. Задача полностью решена.

Ответить

Вернуться в «MapInfo»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя