| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > Зачем проверять IsWindowUnicode перед SetWindowLon |
| Автор: Ruzzz 9.11.2009, 08:00 | ||
Часто вижу такой код (например при написании dll):
Есть ли в этом смысл? Если я компилирую dll как юникод, и будет использоваться SetWindowLongPtrW, а hwndParent допустим будет указывать на не юникод окно, то к чему это может привести? В MSDN в описании SetWindowLongPtr и SetWindowLong ничего не нашел. Учитывая что оконная функция ничем не отличается, то что будет не так? |
| Автор: Earnest 9.11.2009, 09:48 |
| Скорее всего, неродная функция просто не сработает. |
| Автор: Ruzzz 9.11.2009, 10:15 | ||
Сделал так:
Все работает. В чем же причина? |
| Автор: GremlinProg 9.11.2009, 12:21 | ||
| можешь привести пример такой dll? может там все же было что-то вроде такого:
|
| Автор: Ruzzz 9.11.2009, 13:03 |
| GremlinProg, мне уже подсказали что в зависимости от того какой версией SetWindowLongPtr воспользуемся, винда будет слать специфические сообщения или анси или юникодные, а ваш пример еще и показывает что иногда нужно об этом заботиться и подготавливать заранее две версии оконной процедуры. Но как я понимаю если я не «ловлю» такие сообщения, то все равно нужно предусмотреть в своей процедуре разные варианты CallWindowProc, если я вызываю ее для сообщений по умолчанию. Так ли это? Ну и какие еще могут быть ситуаци, которые требуют разных версий оконных процедкр? Мне бы примеры таких сообщений. То есть правильно ли я понял: В зависимости от того оконную процедуру какого окна, юникодного или нет, мы переопределяем, я должен в своей процедуре (или одной или сделать две версии) предусмотреть: - Вызов соответствующий CallWindowProc В зависимости от того какую версию SetWindowLongPtr я использую, винда будет думать что я хочу принимать соотв-щие данные, а значит: - сообщения, со строковыми данными будут «приносить» соответствующие строки (пример бы таких сообщений) - а значит и оконная функция по умолчанию будет соот-щей версии? Так? |
| Автор: Ruzzz 9.11.2009, 13:23 |
| Нашел вот это http://www.codeproject.com/KB/winsdk/safesubclassing.aspx |
| Автор: GremlinProg 9.11.2009, 14:29 | ||||
судя по отзывам, получилось, видимо данные сообщения транслируются в этих двух точках: SetWindowLong и CallWindowProc только вот что будешь делать, когда на разных типах окон будут посылаться разные сами сообщения или уведомления, например то же TVN_GETDISPINFO, которое UNICODE окна отсылают как TVN_GETDISPINFOW(TVN_FIRST-52), а ANSI - как TVN_GETDISPINFOA(TVN_FIRST-3)? разве что проверять в рантайме:
не так уж и удобно SetWindowLong и CallWindowProc не знают ничего о treeview, подменить индекс сообщения они не смогут, так что даже в случае из статьи, к IsWindowUnicode придется вернуться уже в теле процедуры окна, надежнее всего будет просто задать соответствующий вариант процедуры окна |
| Автор: Ruzzz 9.11.2009, 14:44 | ||
| GremlinProg, С сообщениями я все понял, но вот как быть с CallWindowProc и DefWindowProc. Решил что понял, но тут мне ответили на одном форуме: На мои слова: «in gen_tray\TRAYCTL.C line int ret = CallWindowProc(lpOldWinampWndProc,hwnd,message,wParam,lParam); better to replace: if (IsWindowUnicode(hwnd)) CallWindowProcW(lpOldWinampWndProc,hwnd,message,wParam,lParam); else CallWindowProcA(lpOldWinampWndProc,hwnd,message,wParam,lParam);» «Ruzzz: that's not required as the OS will do the relevant mapping based on how you subclassed to begin with. so in this case as long as a SetWindowLongPtrW(GWLP_WNNPROC) is correctly applied then it'll map things through CallWindowProcW(..) as long as nothing else has done a CallWindowProcA(..) or a SetWindowLongPtrA(GWLP_WNNPROC).» при этом они используют:
может они предполагают что компилироваться будет только Юникод-версия? или я не пойму. |
| Автор: GremlinProg 9.11.2009, 15:13 | ||||
я так понимаю, он и пишет, что мол разницы нет что вызывать: SetWindowLongPtrA или SetWindowLongPtrW, т.к. нет необходимости транслировать строки, их там просто нет это уже я не понял ) какой смысл для юникод-окна вызывать ANSI версию, а для ANSI-окна - юникод версию, да еще опираться при этом на родительское окно? разве что в целях эксперимента, чтобы показать, что мол процедура окна у них "симметрична"
ну да, может быть, винамп, по крайней мере, последних версий - в юникоде |
| Автор: Ruzzz 9.11.2009, 15:27 | ||||
| GremlinProg, аааа ) я ошибся, без ! Винамп или сам плохо поддерживает юникод или некоторые модули которые идут с ним, по крайней мере в VirtualBox в XP поменял язык для Ansi приложений и получил кое-где крякозябры в русифицированном винампе, ну да не про это У них в SDK есть строки:
При этом говорят что нет смысла в этом:
Не понимаю почему? Только если они предполагают что этот модуль будет компилироваться как юникод? тогда еще понимаю. То есть будет явно подставлена CallWindowProcW, ну тогда нафига они верхний IsWindowUnicode не уберут? не пойму. |
| Автор: GremlinProg 9.11.2009, 16:34 | ||||
| в принципе, если локаль фиксирована, т.е. четко выставлена при старте в какой-нибудь cp1252, то при такого рода неявных трансляциях сообщений вполне могут проскальзывать и кракозябры, тут же физически производится перевод из MBS в WCS и обратно, если это не учитывать, тут даже не поймешь, где конкретно происходит преобразование, это может быть как в штатной посылке сообщения, так и внутри какой-нибудь API, в любом случае, даже просто из соображений быстродействия программы, лучше выделить 2 варианта оконной процедуры, если сабклассинг применяется в DLL, или делать трансляцию, но в препроцессоре, типа такой:
естественно со всеми вытекающими, т.е. пишем один транс-код, но ориентированный на MY_UNICODE_WNDPROC, а не _UNICODE
тут может быть такой вариант: у них при сабклассинге используется одна кодировка, к примеру - юникод, а в процедуре по-умолчанию - ANSI, когда они подставляли процедуру, не учли или просто не захотели пользоваться вот этой трансляцией (может как раз из-за проблем с интернационализацией), в итоге и получили первый уровень процедуры - юникод, а второй - ANSI, а вместо системного перевода WCS-сообщения в MBS, используют прямой вызов ANSI процедуры, т.е. сделали себе проблему на ровном месте, но это просто предположение, в их SDK я не лазил |
| Автор: Earnest 10.11.2009, 08:18 | ||
Чисто добавление: в данном случае нужно проверять в обработчике код уведомления, а не Юникод. Так обычно и делают, хотя код получается громоздкий. Например, собственный (встроенный) тултип у тривью или листвью всегда Юникодный, даже если само окно не-Юникод. Помниться, как-то помучалась, пока дошло... |
| Автор: Ruzzz 10.11.2009, 14:57 | ||
не совсем понял :( |
| Автор: Ruzzz 10.11.2009, 15:28 |
| Вот еще интересная ссылка http://msdn.microsoft.com/en-us/library/ms997565.aspx |
| Автор: Earnest 10.11.2009, 18:31 |
Ну, в обработчике W_NOTIFY нужно проверять не IsUnicodeWindow, а код уведомления (скажем TTN_NEEDTEXTA или TTN_NEEDTEXTW), т.к. не-Юникод окно вполне может получить Юникод сообщения от своих детей. |