Не получается спрятать/показать Language bar. Наверное нужно использовать функцию CoCreateInstance с интерфейсом ITfLangBarMgr. Как это реализовать на ассемблере?
baldr Code (Text): invoke CoCreateInstance,CLSID_TF_LangBarMgr,NULL,CLSCTX_INPROC_SERVER,IID_ITfLangBarMgr,(не знаю) Ругается на CLSID_TF_LangBarMgr и IID_ITfLangBarMgr (undefined symbol).
Code (Text): .386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\ole32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\ole32.lib .data? pUnk dd ? .const cls GUID <0ebb08c45h,06c4ah,04fdch,<0aeh,053h,04eh,0b8h,0c4h,0c7h,0dbh,08eh>> iid GUID <087955690h,0e627h,011d2h,<08h,0ddh,00h,010h,05ah,027h,099h,0b5h>> .code start: invoke CoCreateInstance,offset cls,NULL,CLSCTX_INPROC_SERVER,offset iid,offset pUnk invoke ExitProcess,NULL end start Удивительно, что функция CoCreateInstance не вернула ни одного из значений: S_OK, REGDB_E_CLASSNOTREG, CLASS_E_NOAGGREGATION, E_NOINTERFACE, E_POINTER.
Значит, так оно и есть. Я в своём реестре (XP SP2) тоже не нашёл регистрации класса {ebb08c45-6c4a-4fdc-ae534eb8c4c7db8e}.
У меня в реестре есть эта ветвь. Если её удалить, то получишь ошибку REGDB_E_CLASSNOTREG. Настраивая визуальные эффекты, языковая панель исчезает и появляется, причём ctfmon остаётся в списке запущенных процессов. Значит, задача имеет решение.
msctf.dll экспортирует TF_CreateLangBarMgr(). Она, вроде, работает (без всяких CoInitialize(), методы интерфейса я не трогал). Кстати, iid не совсем правильный: не <08h,0ddh,00h, а <08dh,0dbh,00h, — это я подглядел в msctf.dll.
baldr Из-за невнимательности указал неверный iid. Сейчас функция возвращает S_OK. Следующая строчка на си выглядит приблизительно так: Code (Text): pUnk->ShowFloating(TF_SFT_HIDDEN) Не знаю как её записать на ассемблере.
Указатель на интерфейс ссылается на dword с адресом таблицы адресов методов интерфейса. Первые три из IUnknown, остальные согласно ITfLangBarMgr. Т.е. что-то вроде Code (Text): push TF_SFT_HIDDEN ; dwFlags mov eax, [pUnk] push eax ; this mov eax, [eax] call [eax+40] ; Vtbl.ShowFloating
baldr Code (Text): .const LibName db "msctf.dll",0 FunctionName db "TF_CreateLangBarMgr",0 .code start: invoke LoadLibrary,addr LibName invoke GetProcAddress,eax,addr FunctionName mov eax,[eax] call eax invoke ExitProcess,NULL end start Ошибка при запуске.
gale1238, Естественно, ошибка. Какое отношение первый dword (почти наверняка 0x8b55ff8b) функции TF_CreateLangBarMgr() имеет к тому, что я написал про вызов метода интерфейса COM-объекта? Это про использование значения (указателя на ITfLangBarMgr), которое вызов этой функции возвращает.
baldr Пытаюсь получить указатель на интерфейс, запуская функцию TF_CreateLangBarMgr из dll'ки без инициализации COM-объекта. Нет желания связываться с реестром. Если можете, помогите, пожалуйста.
Вроде всё уже есть: Code (Text): format PE GUI include "Win32A.Inc" interface ITfLangBarMgr,\ QueryInterface,\; IUnknown AddRef,\ Release,\ AdviseEventSink,\; ITfLangBarMgr UnadviseEventSink,\ GetThreadMarshalInterface,\ GetThreadLangBarItemMgr,\ GetInputProcessorProfiles,\ RestoreLastFocus,\ SetModalInput,\ ShowFloating,\ GetShowFloatingStatus define TF_SFT_SHOWNORMAL 0x00000001 define TF_SFT_DOCK 0x00000002 define TF_SFT_MINIMIZED 0x00000004 define TF_SFT_HIDDEN 0x00000008 define TF_SFT_NOTRANSPARENCY 0x00000010 define TF_SFT_LOWTRANSPARENCY 0x00000020 define TF_SFT_HIGHTRANSPARENCY 0x00000040 define TF_SFT_LABELS 0x00000080 define TF_SFT_NOLABELS 0x00000100 define TF_SFT_EXTRAICONSONMINIMIZED 0x00000200 define TF_SFT_NOEXTRAICONSONMINIMIZED 0x00000400 define TF_SFT_DESKBAND 0x00000800 ; Здесь всё начинается… invoke TF_CreateLangBarMgr, LangBarMgr cominvk LangBarMgr, ShowFloating, TF_SFT_HIDDEN cominvk LangBarMgr, Release ; Вот вроде и всё. ret LangBarMgr ITfLangBarMgr data import library MSCTF, "MSCTF.DLL" import MSCTF, TF_CreateLangBarMgr, "TF_CreateLangBarMgr" end data Это для FASM. Код простой: вызвать TF_CreateLangBarMgr(&LangBarMgr), потом вызвать LangBarMgr->ShowFloating(TF_SFT_HIDDEN), ну и LangBarMgr->Release(). Остальное — обвязка (data import вместо LoadLibrary()/GetProcAddress(), макрос interface чтобы не высчитывать смещение ShowFloating(), макрос cominvk развёртывается в то, что я привёл ранее).
Разве можно так лениться? Code (Text): invoke LoadLibrary, addr LibName invoke GetProcAddress, eax, addr FunctionName push offset LangBarMgr call eax push 8 ; TF_SFT_HIDDEN mov ebx, [LangBarMgr] push ebx ; this mov esi, [ebx] call near ptr [esi+40]; Vtbl.ShowFloating push ebx ; this call near ptr [esi+8]; Vtbl.Release
baldr, спасибо за помощь. Хочу оформить в в виде процедуры. Code (Text): .const LibName db "msctf.dll",0 FunctionName db "TF_CreateLangBarMgr",0 .code LangBar proc local hMSCTF:dword local ppv:dword invoke LoadLibrary,addr LibName mov hMSCTF,eax invoke GetProcAddress,eax,addr FunctionName push [ppv] ;push offset ppv не компилируется call eax ;здесь зависает .......................... invoke FreeLibrary,hMSCTF ret LangBar endp .code start: call LangBar invoke ExitProcess,NULL end start
Когда языковая панель прячется, то одновременно полоса панели задач становится уже на 2 пикселя. Чтобы вернуть размер прямоугольнику делаю следующее: Code (Text): invoke SystemParametersInfo,SPI_GETWORKAREA,0,addr pRect,SPIF_UPDATEINIFILE or SPIF_SENDCHANGE dec pRect.bottom invoke SystemParametersInfo,SPI_SETWORKAREA,0,addr pRect,SPIF_UPDATEINIFILE or SPIF_SENDCHANGE Но вначале нужно обязательно восстановить языковую панель. Может есть другой способ, не такой топорный?