c# Можно ли перехватить событие в PrintDialog-е ?
Мне нужно вызвать свой код в момент когда юзер меняет принтер в этом комбобоксе.
Это возможно?
...................................
А именно, что я хочу там сделать, так это загрузить ранее сохраненный PrinterSettings.
Дело в том что есть у нас спец принтер, который наклейки теромпечатью штампует, но нерадивые программисты (я их не знаю), которые писали драйвер принтера, не сохраняют нигде изменения. Поэтому каждый раз перед печатью приходится настройки принтера делать заново. Еще такая бяка: стоит юзеру выбрать другой принтер в комбобоксе, а потом опять наш нужный - настройки у принтера сбрасываются и опять приходится настраивать.
................
Конечно совсем не сложно написать свой собственный подобный диалог. Но перехватить событие комбобокса, если это возможно, я надеюсь - проще.
Вся эта печать происходит из программы, исходники которой в наличии, и там делается стандартно new PrintDialog и т.д.
PrinterSettings устанавливать не до а после показа диалога?
Речь вообще про Winforms?
Чо-нить типа того:
var dialog= new PrintDialog();
If (dialog.ShowDialog()=DialogResult.OK)
{
If (dialog.PrinterSettings.PrinterName==„thermo“)
dialog.PrinterSettings=mySettings;
}
Да, Winforms.
Частично решает проблему такая последовательность:
var dialog= new PrintDialog();
dialog.PrinterSettings=LoadSettingsOfDefaultPrinter();
If (dialog.ShowDialog()==DialogResult.OK)
{
....SaveSettings( dialog.PrinterSettings);
....SetDefaultPtinter(dialog.PrinterSettings.PrinterName);
}
Причем сохранять/загружать в отдельный файл для каждого принтера. Ну а если файла еще нет, то ничего не грузить.
Но в прошлом посте я указал на "бяку".
Пусть дефаулт принтер сейчас именно наш. Юзер открывает диалог и настройки принтера прочтены с диска. Все хорошо.
Но если юзер даже случайно лишь кликнет по комбобоксу и на секундочку там окажется другой принтер, в этот момент прочтенные настройки уже потеряны, там уже настройки "по умолчанию". И если теперь юзер вернет в комбобоксе наш принтер и кликнет ОК - файл будет перезаписан настойками "по умолчанию".
Т.е. очень легко испортить файл настроек.
Решается это кажись только так: загружать настройки нужно в момент обновления значения в комбобоксе.
......
Но я не нашел в PrintDialoge как к этом комбобоксу добраться. Может есть какой нестандартный способ?
Может есть какой нестандартный способ?
Думал это, но не пойдет, нужно видимо через дескрипторы окон делать, диалог то из винды прямо.
reflection можно попробовать. Но нужно много компов перебрать, чтобы на всех работало
Как направление:
https://www.c-sharpcorner.com/UploadFile/75a48f/how-to-acc...
но лучше свое написать
https://referencesource.microsoft.com/#system.windows.form...
Причем сохранять/загружать в отдельный файл для каждого принтера.
------
Не надо для каждого. Надо - именно для вашего специфического.
Именно по-этому тебе предлагалось не делать для всех, а по Диалог.Ок проверить имя принтера и загрузить его настройки.
Да, каждый раз, независимо от того какой текущий - трекать изменения там сложно - надо лезть в MFC-шный PrintDialog
а в нем происходит сборка диалога путем внедрения элементов...
Детали - не помню - как-то оооочень давно ковырял диалоги на предмет модификации - помню, что можно, но не помню как...
Может есть какой нестандартный способ?
-----
Скорее - стандартный.
WinSpi - получить хандле окна листбокса и повесить на него свой обработчик очереди сообщений.
Но, пожалуй, тоже не пойдет - листбокс становится доступен ПОСЛЕ ШовДиалог, а ШовДиалог - модальный для кода...
Из бредовых идей...
Нарисовать поверх диалогового комбобокса - свой с перекрытыми евентами.
Размер и позиция там фиксированные - можно накрыть, перехватить и перевыбрать...
Примеры выборки и заполнения есть на стацковерфлоv...
https://stackoverflow.com/a/22403380
А дальше поиск combobox'а и window subclassing
Решение зависит от внутренней имплементации диалога как в .NET, так и в Windows, а поэтому не надежное.
Но, по-моему, это единственный вариант без реализации собственного диалога.
Чью именно? ДотНет класса?
Именно для подобных как у ТС задач этот метод и предназначен. С каким-нибудь другим диалогом перегрузкой этого метода все бы и закончилось, Но, к сожалению, sealed.
Так у него ДРУГАЯ очередь...
Та же самая.
От оригинального ПринтДиалога там только хандле и тот только в процессе выполнения ШовДиалог...
Там все от оригинального диалога.
Чью именно? ДотНет класса? Так у него ДРУГАЯ очередь...У 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 в ДотНете - это вполне себе годный вариант. Никакой "другой" очереди там нет. Очередь одна.
var dialog= new PrintDialog();
dialog.PrinterSettings=LoadSettingsOfDefaultPrinter();
If (dialog.ShowDialog()==DialogResult.OK)
я все же не понял, зачем тебе нужно устанавливать PrinterSettings до показа диалога, когда известно, что они впоследствии перезапишутся?
Почему не делать этого посте?
ну это есл юзер кликнет по кропке "Свойсва", чтобы там отобразились загруженный настройки.var dialog= new PrintDialog(); dialog.PrinterSettings=LoadSettingsOfDefaultPrinter(); If (dialog.ShowDialog()==DialogResult.OK)я все же не понял, зачем тебе нужно устанавливать PrinterSettings до показа диалога, когда известно, что они впоследствии перезапишутся? Почему не делать этого посте?
Но я уже тему закрыл собственным диалогом. При изменении (и инициализации) комбобокса новым принтером, я загружаю ранее сохраненные данные (если таковые имеются). При закрытии спец диалога (что по кнопке "Свойства" открываются) я сохраняю свойства в файл (можно перед открытием его грузить). При ОК (моего) ПринтДиалога, я устанавливаю дефаулт принтер системы. А перед самой печатью, загружаю (если есть что грузить) из файла свойства и печатаю. (саму печать можно и без этого диалога запустить)
....
Можно было и чуть по другому сделать, получше - сохраненные файлы показывать наряду со всеми принтерами в комбобоксе, а сохранять в файл по дополнительной кнопке "Сохранить". Но и так устраивает.