Доброго времени суток! Вот написал небольшую программу, которая должна менять шрифт в открытом окне блокнота: Код (Text): format PE GUI 4.0 include 'win32ax.inc' .data notepad db 'notepad', 0 _font db 'Courier',0 .code start: invoke FindWindow, notepad, 0 invoke SendMessage, eax, WM_SETFONT, _font, 1 invoke ExitProcess, 0 .end start Программа не работает. Думаю, что неправильно задал шрифт, но не знаю как его правиьно задать. Как все же программно поменять шрифт? P.S. Странно, но у каждого файла свой шрифт, я думал что это настройка самого приложения.
вообще то, насколько я помню, передавать надо хэндл на FONT, а не название шрифта иначе юзается системный
Обрывок на С. Последовательность та же. Код (Text): LOGFONT LF; memset(&LF,0,sizeof(LOGFONT)); // zero out structure LF.lfHeight = 16; // request a 16-pixel-height font strcpy(LF.lfFaceName,"Courier New"); // request a face name VERIFY(_Font.CreateFontIndirect(&LF)); // create the font m_List.SetFont(&_Font,FALSE);
emptyHook, Код (Text): LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ... switch (message) { case WM_PAINT: ... CreateFont ...и так пару раз; веселый паровоз, если каждую прорисовку так делать
MFC, если вы настаиваете на деталях. Но в данном случае, это неважно. Последовательность та же. Вот, для примера, кусочек на чистом API: Код (Text): LRESULT CALLBACK OwnerDraw_Callback ( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { switch (uiMsg) { case WM_SETCURSOR: { // } case WM_LBUTTONDOWN: { // } case WM_LBUTTONUP: { // } case WM_PAINT: { PAINTSTRUCT ps; HDC dc = BeginPaint(hWnd,&ps); // Create underlined font LOGFONT lf; HFONT hFont = (HFONT)SendMessage(GetParent(hWnd),WM_GETFONT,0,0); GetObject(hFont,sizeof(lf),&lf); lf.lfUnderline = TRUE; hFont = CreateFontIndirect(&lf); // Get text to draw int len = GetWindowTextLength(hWnd); char str[MAX_PATH]; len = GetWindowText(hWnd,str,len + 1); // Prepare DC COLORREF cr = SetTextColor(dc,RGB(0,0,255)); HGDIOBJ hOldFont = SelectObject(dc,hFont); int bk = SetBkMode(dc,TRANSPARENT); // Draw RECT rc; GetClientRect(hWnd,&rc); DrawText(dc,str,len,&rc,DT_SINGLELINE | DT_NOPREFIX | DT_CENTER); // Unprepare DC SelectObject(dc, hOldFont); SetBkMode(dc, bk); SetTextColor(dc, cr); DeleteObject(hFont); // Finish EndPaint(hWnd,&ps); return 0; } } return DefWindowProc(hWnd,uiMsg,wParam,lParam); }
Спасибо большое, дело заметно продвинулось. Особенно громаднейшее спасибо edemko за информативный исходник: очень помогло рассмотрение того, как это всё реализуется на практике. Программа находит текстовое поле, и даж пишет туда текст. Но проблема в том, что шрифт по какой-то причине не поменялся. Код (Text): format PE GUI 4.0 include 'win32ax.inc' .data notepad db 'notepad', 0 hw rd 4 ;хэндл верхнего окна hchild rd 4 ;хэндл дочернего окна hFont rd 4 ;шрифт ClassName rd 1 ;здесь храним имя класса дочернего окна lf LOGFONT \ 12,7,\ ;lfHeight & lfWidth 0,0,\ ;lfEscapement(наклон отн. Х в 10х градуса) & lfOrientation FW_NORMAL,0,0,0,\ ;lfWeight & lfItalic & lfUnderline & lfStrikeOut RUSSIAN_CHARSET,\ ;lfCharSet OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\ ;lfOutPrecision & lfClipPrecision & lfQuality FF_MODERN+FIXED_PITCH,\ ;lpPitchAndFamily ;FIXED_PITCH=моноширинный=красивосорцен Ж) 'lucida console' ;lfFaceName .code start: invoke ShellExecute,NULL,NULL,'notepad.exe',NULL,NULL,SW_SHOW invoke MessageBox,HWND_DESKTOP,"Запуск Блокнота",0,0 invoke CreateFontIndirectA,lf ;создание шрифта mov [hFont],eax invoke FindWindow, notepad, 0 mov [hw],eax invoke EnumChildWindows,[hw],EnumChildProc, NULL invoke SendMessage,[hchild],WM_SETTEXT,100,"аБвГд" invoke MessageBox,HWND_DESKTOP,"Теперь поменяем шрифт (в любом случае, последние две буквы поменяют регистр)",0,0 invoke SendDlgItemMessageA,hchild,3,WM_SETFONT,[hFont],TRUE ;FALSE invoke SendMessage,hchild,3,WM_SETFONT,[hFont],TRUE ;FALSE ;какая-то из двух предыдущих должна заработать invoke SendMessage,[hchild],WM_SETTEXT,100,"аБвгД" invoke ExitProcess, 0 proc EnumChildProc hwchild,NULL push ebx esi edi invoke GetClassName, [hwchild],ClassName,5 ;Ищем по классу cmp [ClassName],"Edit" ;сравниваем с искомым je equi finish: pop edi esi ebx ret equi: mov eax,0 invoke MessageBox,HWND_DESKTOP,"Найден класс Edit",0,0 mov eax,[hwchild] mov [hchild],eax jmp finish endp .end start Я там ввёл сразу две функции изменения шрифта, чтоб наверняка.
В отличие от WM_SETTEXT, WM_SETFONT - не транзитивный: блокнот будет искать посланные ему шрифт где-то в своем адресном пространстве. Код (Text): format pe gui 4.0 include 'win32ax.inc' section '' code executable import readable writable library gdi32,'gdi32.dll',\ kernel32,'kernel32.dll',\ user32,'user32.dll' include 'api\gdi32.inc' include 'api\kernel32.inc' include 'api\user32.inc' lf LOGFONT \ 12,7,\ ;lfHeight & lfWidth 0,0,\ ;lfEscapement(наклон отн. Х в 10х градуса) & lfOrientation FW_NORMAL,0,0,0,\ ;lfWeight & lfItalic & lfUnderline & lfStrikeOut RUSSIAN_CHARSET,\ ;lfCharSet OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\ ;lfOutPrecision & lfClipPrecision & lfQuality FF_MODERN+FIXED_PITCH,\ ;lpPitchAndFamily ;FIXED_PITCH=моноширинный=красивосорцен Ж) 'courier new' ;lfFaceName hw rd 1 hf rd 1 entry $ invoke FindWindowExA,<invoke FindWindowA,'notepad',0>,0,'edit',0 mov [hw],eax invoke SendMessageA,eax,WM_SETTEXT,0,'fedc''ba98''7654''3210' invoke CreateFontIndirectA,lf mov [hf],eax invoke SendMessageA,[hw],WM_SETFONT,eax,TRUE invoke ExitProcess,0
Снова одна проблема: я создаю второй шрифт (такой же, только подчёркнут), но шрифт остаётся таким же, не понимаю в чём может быть дело. Код (Text): format pe gui 4.0 include 'win32ax.inc' section '' code executable import readable writable library gdi32,'gdi32.dll',\ kernel32,'kernel32.dll',\ user32,'user32.dll' include 'api\gdi32.inc' include 'api\kernel32.inc' include 'api\user32.inc' lf1 LOGFONT \ 12,7,\ ;lfHeight & lfWidth 0,0,\ ;lfEscapement(наклон отн. Х в 10х градуса) & lfOrientation FW_NORMAL,0,0,0,\ ;lfWeight & lfItalic & lfUnderline & lfStrikeOut RUSSIAN_CHARSET,\ ;lfCharSet OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\ ;lfOutPrecision & lfClipPrecision & lfQuality FF_MODERN+FIXED_PITCH,\ ;lpPitchAndFamily ;FIXED_PITCH=моноширинный=красивосорцен Ж) 'courier new' ;lfFaceName lf2 LOGFONT \ 12,7,\ ;lfHeight & lfWidth 0,0,\ ;lfEscapement(наклон отн. Х в 10х градуса) & lfOrientation FW_NORMAL,0,TRUE,0,\ ;lfWeight & lfItalic & lfUnderline & lfStrikeOut RUSSIAN_CHARSET,\ ;lfCharSet OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\ ;lfOutPrecision & lfClipPrecision & lfQuality FF_MODERN+FIXED_PITCH,\ ;lpPitchAndFamily ;FIXED_PITCH=моноширинный=красивосорцен Ж) 'courier new' hw rd 1 hf rd 1 entry $ invoke MessageBoxA,HWND_DESKTOP,"Шрифт по настройкам меню",0,0 invoke FindWindowExA,<invoke FindWindowA,'notepad',0>,0,'edit',0 mov [hw],eax invoke SendMessageA,[hw],WM_SETTEXT,0,'fedc''ba98''7654''3210' invoke MessageBox,HWND_DESKTOP,"Изменённый шрифт(первый вариант)",0,0 invoke CreateFontIndirectA,lf1 mov [hf],eax invoke SendMessageA,[hw],WM_SETFONT,eax,TRUE invoke MessageBox,HWND_DESKTOP,"Изменённый шрифт(второй вариант)",0,0 invoke CreateFontIndirectA,lf2 mov [hf],eax invoke SendMessageA,[hw],WM_SETFONT,0,TRUE invoke ExitProcess,0
WM_SETFONT действует в рамках одного приложения. ВСЕ НИЖЕ К ЭТОЙ ТЕМЕ ОСОБОГО ОТНОШЕНИЯ НЕ ИМЕЕТ Нашел медведь здоровую бочку меда. Пошол домой за повозкой, на бочке написал "бочка пуста и меда в ней нет". Вернулся и видит надпись: "ежик мед не трогал". Странно, но notepad.exe на прорисовках создает заново шрифт. Глупо. Ниже рисунок, как блокнот меняет шрифт после ШрифтДиалога(ChoseFontW). А перед этим видим такую строчку: Код (Text): CPU Disasm Address Hex dump Command Comments 01003052 |. BF 20AB0001 mov edi,offset notepad.0100AB20
Не совсем. Послать-то его можно, но в контексте устройства для окна-приёмника будет выбран "System, 8pt" (шрифт по умолчанию). Кстати, с термином «транзитивность» вольничать — некорректно.