Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

c# Можно ли перехватить событие в PrintDialog-е ?

683  
anly коренной житель30.03.19 20:51
anly
NEW 30.03.19 20:51 
Последний раз изменено 30.03.19 21:01 (anly)

Мне нужно вызвать свой код в момент когда юзер меняет принтер в этом комбобоксе.

Это возможно?

...................................

А именно, что я хочу там сделать, так это загрузить ранее сохраненный PrinterSettings.

Дело в том что есть у нас спец принтер, который наклейки теромпечатью штампует, но нерадивые программисты (я их не знаю), которые писали драйвер принтера, не сохраняют нигде изменения. Поэтому каждый раз перед печатью приходится настройки принтера делать заново. Еще такая бяка: стоит юзеру выбрать другой принтер в комбобоксе, а потом опять наш нужный - настройки у принтера сбрасываются и опять приходится настраивать.

................

Конечно совсем не сложно написать свой собственный подобный диалог. Но перехватить событие комбобокса, если это возможно, я надеюсь - проще.

Вся эта печать происходит из программы, исходники которой в наличии, и там делается стандартно new PrintDialog и т.д.

Проклят нарушающий межи ближнего своего (Втор.27:17)
#1 
Срыв покровов коренной житель31.03.19 00:54
31.03.19 00:54 
в ответ anly 30.03.19 20:51

PrinterSettings устанавливать не до а после показа диалога?

Речь вообще про Winforms?


Чо-нить типа того:

var dialog= new PrintDialog();

If (dialog.ShowDialog()=DialogResult.OK)

{

If (dialog.PrinterSettings.PrinterName==„thermo“)

dialog.PrinterSettings=mySettings;

}


#2 
anly коренной житель31.03.19 10:04
anly
NEW 31.03.19 10:04 
в ответ Срыв покровов 31.03.19 00:54

Да, Winforms.

Частично решает проблему такая последовательность:

var dialog= new PrintDialog();

dialog.PrinterSettings=LoadSettingsOfDefaultPrinter();

If (dialog.ShowDialog()==DialogResult.OK)

{

....SaveSettings( dialog.PrinterSettings);

....SetDefaultPtinter(dialog.PrinterSettings.PrinterName);

}

Причем сохранять/загружать в отдельный файл для каждого принтера. Ну а если файла еще нет, то ничего не грузить.

Но в прошлом посте я указал на "бяку".

Пусть дефаулт принтер сейчас именно наш. Юзер открывает диалог и настройки принтера прочтены с диска. Все хорошо.

Но если юзер даже случайно лишь кликнет по комбобоксу и на секундочку там окажется другой принтер, в этот момент прочтенные настройки уже потеряны, там уже настройки "по умолчанию". И если теперь юзер вернет в комбобоксе наш принтер и кликнет ОК - файл будет перезаписан настойками "по умолчанию".

Т.е. очень легко испортить файл настроек.

Решается это кажись только так: загружать настройки нужно в момент обновления значения в комбобоксе.

......

Но я не нашел в PrintDialoge как к этом комбобоксу добраться. Может есть какой нестандартный способ?

Проклят нарушающий межи ближнего своего (Втор.27:17)
#3 
AlexNek патриот31.03.19 12:09
AlexNek
NEW 31.03.19 12:09 
в ответ anly 31.03.19 10:04
Может есть какой нестандартный способ?

Думал это, но не пойдет, нужно видимо через дескрипторы окон делать, диалог то из винды прямо.


reflection можно попробовать. Но нужно много компов перебрать, чтобы на всех работало

Как направление:

https://www.c-sharpcorner.com/UploadFile/75a48f/how-to-acc...


но лучше свое написать

https://referencesource.microsoft.com/#system.windows.form...


#4 
Murr патриот01.04.19 11:50
Murr
NEW 01.04.19 11:50 
в ответ anly 31.03.19 10:04

Причем сохранять/загружать в отдельный файл для каждого принтера.

------

Не надо для каждого. Надо - именно для вашего специфического.

Именно по-этому тебе предлагалось не делать для всех, а по Диалог.Ок проверить имя принтера и загрузить его настройки.

Да, каждый раз, независимо от того какой текущий - трекать изменения там сложно - надо лезть в MFC-шный PrintDialog

а в нем происходит сборка диалога путем внедрения элементов...

Детали - не помню - как-то оооочень давно ковырял диалоги на предмет модификации - помню, что можно, но не помню как...


Может есть какой нестандартный способ?

-----

Скорее - стандартный.

WinSpi - получить хандле окна листбокса и повесить на него свой обработчик очереди сообщений.

Но, пожалуй, тоже не пойдет - листбокс становится доступен ПОСЛЕ ШовДиалог, а ШовДиалог - модальный для кода...



Из бредовых идей...

Нарисовать поверх диалогового комбобокса - свой с перекрытыми евентами.

Размер и позиция там фиксированные - можно накрыть, перехватить и перевыбрать...

Примеры выборки и заполнения есть на стацковерфлоv...

#5 
Murr патриот01.04.19 11:54
Murr
NEW 01.04.19 11:54 
в ответ AlexNek 31.03.19 12:09

reflection можно попробовать.

-----

Нельзя.

Там используется старый MFC-шный PrintDialog.

В .Нет - только оболочка над его частью.


но лучше свое написать

-----

Когда пороешься, то поймешь что там нет списка принтеров.

#6 
NightWatch коренной житель01.04.19 12:33
NightWatch
NEW 01.04.19 12:33 
в ответ anly 31.03.19 10:04

https://stackoverflow.com/a/22403380

А дальше поиск combobox'а и window subclassing

Решение зависит от внутренней имплементации диалога как в .NET, так и в Windows, а поэтому не надежное.

Но, по-моему, это единственный вариант без реализации собственного диалога.

#7 
NightWatch коренной житель01.04.19 12:35
NightWatch
NEW 01.04.19 12:35 
в ответ Murr 01.04.19 11:54
Там используется старый MFC-шный PrintDialog.

Там используется WinAPI. И подозреваю, что MFC-шный класс - тоже оболочка.

#8 
AlexNek патриот01.04.19 13:00
AlexNek
NEW 01.04.19 13:00 
в ответ Murr 01.04.19 11:54

так я специально италиком сделал, когда понял что низзя.

Надо глянуть что на WPF мы делали, "его" можно в винформс добавить.

#9 
Программист коренной житель01.04.19 14:09
NEW 01.04.19 14:09 
в ответ anly 30.03.19 20:51

А если унаследоваться от PrintDialog и перегрузить HookProc? Соответственно дальше случаешь CBN_SELCHANGE и реагируешь так, как тебе надо?

#10 
Murr патриот01.04.19 17:08
Murr
NEW 01.04.19 17:08 
в ответ NightWatch 01.04.19 12:35

подозреваю, что MFC-шный класс - тоже оболочка

------

Возможно.

Диалоги в Винде - это диалоги в Винде - нужную форму сделать много проще, чем пострoить диалог...

#11 
Murr патриот01.04.19 17:12
Murr
NEW 01.04.19 17:12 
в ответ Программист 01.04.19 14:09

перегрузить HookProc?

-----

Чью именно? ДотНет класса? Так у него ДРУГАЯ очередь...

От оригинального ПринтДиалога там только хандле и тот только в процессе выполнения ШовДиалог...

#12 
NightWatch коренной житель01.04.19 17:26
NightWatch
NEW 01.04.19 17:26 
в ответ Murr 01.04.19 17:12, Последний раз изменено 01.04.19 17:27 (NightWatch)
Чью именно? ДотНет класса?

Именно для подобных как у ТС задач этот метод и предназначен. С каким-нибудь другим диалогом перегрузкой этого метода все бы и закончилось, Но, к сожалению, sealed.

Так у него ДРУГАЯ очередь...

Та же самая.

От оригинального ПринтДиалога там только хандле и тот только в процессе выполнения ШовДиалог...

Там все от оригинального диалога.

#13 
Программист коренной житель01.04.19 17:27
NEW 01.04.19 17:27 
в ответ Murr 01.04.19 17:12
Чью именно? ДотНет класса? Так у него ДРУГАЯ очередь...
У PrintDialog'а (который является наследником CommonDialog) есть
//
// Summary:
// Defines the common dialog box hook procedure that is overridden to add specific
// functionality to a common dialog box.
//
// Parameters:
// hWnd:
// The handle to the dialog box window.
//
// msg:
// The message being received.
//
// wparam:
// Additional information about the message.
//
// lparam:
// Additional information about the message.
//
// Returns:
// A zero value if the default dialog box procedure processes the message; a nonzero
// value if the default dialog box procedure ignores the message.
protected virtual IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam);

И есть еще

//
// Summary:
// Defines the owner window procedure that is overridden to add specific functionality
// to a common dialog box.
//
// Parameters:
// hWnd:
// The window handle of the message to send.
//
// msg:
// The Win32 message to send.
//
// wparam:
// The wparam to send with the message.
//
// lparam:
// The lparam to send with the message.
//
// Returns:
// The result of the message processing, which is dependent on the message sent.
protected virtual IntPtr OwnerWndProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam);
От оригинального ПринтДиалога там только хандле и тот только в процессе выполнения ШовДиалог...

Не только. Ну и обработка сообщений от WinForms в ДотНете - это вполне себе годный вариант. Никакой "другой" очереди там нет. Очередь одна.

#14 
Программист коренной житель01.04.19 17:28
NEW 01.04.19 17:28 
в ответ NightWatch 01.04.19 17:26
Но, к сожалению, sealed.

Слона-то я и не приметил :D

#15 
Срыв покровов коренной житель03.04.19 20:58
NEW 03.04.19 20:58 
в ответ anly 31.03.19 10:04
var dialog= new PrintDialog();
dialog.PrinterSettings=LoadSettingsOfDefaultPrinter();
If (dialog.ShowDialog()==DialogResult.OK)

я все же не понял, зачем тебе нужно устанавливать PrinterSettings до показа диалога, когда известно, что они впоследствии перезапишутся?

Почему не делать этого посте?


#16 
anly коренной житель03.04.19 21:22
anly
NEW 03.04.19 21:22 
в ответ Срыв покровов 03.04.19 20:58, Последний раз изменено 03.04.19 21:36 (anly)
var dialog= new PrintDialog(); dialog.PrinterSettings=LoadSettingsOfDefaultPrinter(); If (dialog.ShowDialog()==DialogResult.OK)
я все же не понял, зачем тебе нужно устанавливать PrinterSettings до показа диалога, когда известно, что они впоследствии перезапишутся? Почему не делать этого посте?
ну это есл юзер кликнет по кропке "Свойсва", чтобы там отобразились загруженный настройки.

Но я уже тему закрыл собственным диалогом. При изменении (и инициализации) комбобокса новым принтером, я загружаю ранее сохраненные данные (если таковые имеются). При закрытии спец диалога (что по кнопке "Свойства" открываются) я сохраняю свойства в файл (можно перед открытием его грузить). При ОК (моего) ПринтДиалога, я устанавливаю дефаулт принтер системы. А перед самой печатью, загружаю (если есть что грузить) из файла свойства и печатаю. (саму печать можно и без этого диалога запустить)

....

Можно было и чуть по другому сделать, получше - сохраненные файлы показывать наряду со всеми принтерами в комбобоксе, а сохранять в файл по дополнительной кнопке "Сохранить". Но и так устраивает.

Проклят нарушающий межи ближнего своего (Втор.27:17)
#17