Мы еще немного поэкспериментируем, то
Мы еще немного поэкспериментируем, то есть фонт и цвет.
Вы можете скачать пример здесь.
Теория:
Цветовая система Windows базируется на RGB значениях, R=красный, G=зеленый, B=синий. Если вы хотите указать Windows цвет, вы должны определить желаемый цвет в системе этих трех основных цветов. Каждое цветовое значение имеет область определения от 0 до 255. Hапример, если вы хотите чистый красный цвет, вам следует использовать 255, 0, 0. Или если вы хотите чистый белый цвет, вы должны использовать 255, 255, 255. Вы можете видеть из примеров, что получение нужного цвета очень сложно, используя эту систему, так что вам нужно иметь хорошее "чувство на цвета", как мешать и составлять их. Для установки цвета текста или фона, вы можете использовать SetTextColor и SetBkColor, оба из которых требуют хэндл контекста устройства и 32-битное RGB значение. Структура 32-битного RGB значения определена как:
RGB_value struct
unused db 0 blue db ? green db ? red db ?
RGB_value ends
Заметьте, что первый байт не используется и должен быть нулем. Порядок оставшихся байтов перевернут, то есть blue, green, red. Тем не менее, мы не будем использовать эту структуру, так как ее тяжело инициализовать и использовать. Вместо этого мы создадим макрос. Он будет получать три параметра: значения красного, зеленого и синего. Он будет выдавать желаемое 32-битное RGB значение и сохранять его в eax. Макрос определен следующим образом:
RGB macro red,green,blue
xor eax,eax mov ah,blue shl eax,8 mov ah,green mov al,red
endm
Вы можете поместить этот макрос в include файл для использования в будущем. Вы можете "создать" фонт, вызвав CreateFont или CreateFontIndirect. pазница между ними заключается в том, что CreateFontIndirect получает только один параметр: указатель на структуру логического фонта, LOGFONT.
СreateFontIndirect более гибкая функция из этих двух, особенно если вашей программе необходимо часто менять фонты. Тем не менее, в нашем примере мы "создадим" только один фонт для демонстрации, поэтому будем делать это через CreateFont. После вызова этой функции, она вернет хэндл фонта, который вы должны выбрать в определенном контексте устройства. После этого, каждая текстовая API функция будет использовать фонт, который мы выбрали.
Содержимое:
.386 .model flat,stdcall option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\gdi32.lib
RGB macro red,green,blue xor eax,eax
mov ah,blue shl eax,8 mov ah,green mov al,red
endm
.data
ClassName db "SimpleWinClass",0 AppName db "Our First Window",0 TestString db " Win32 assembly is great and easy!",0 FontName db "script",0
.data? hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
start: invoke GetModuleHandle, NULL mov hInstance,eax invoke GetCommandLine
mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL wc:WNDCLASSEX LOCAL msg:MSG LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra,NULL mov wc.cbWndExtra,NULL push hInst pop wc.hInstance mov wc.hbrBackground,COLOR_WINDOW+1 mov wc.lpszMenuName,NULL mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax
invoke RegisterClassEx, addr wc invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd .WHILE TRUE invoke GetMessage, ADDR msg,NULL,0,0 .BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .ENDW mov eax,msg.wParam
ret WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM LOCAL hdc:HDC LOCAL ps:PAINTSTRUCT LOCAL hfont:HFONT
.IF uMsg==WM_DESTROY invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_PAINT invoke BeginPaint,hWnd, ADDR ps mov hdc,eax invoke CreateFont,24,16,0,0,400,0,0,0,OEM_CHARSET,\ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\ DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\ ADDR FontName
invoke SelectObject, hdc, eax mov hfont,eax RGB 200,200,50
invoke SetTextColor,hdc,eax RGB 0,0,255 invoke SetBkColor,hdc,eax invoke TextOut,hdc,0,0,ADDR TestString,SIZEOF TestString
invoke SelectObject,hdc, hfont invoke EndPaint,hWnd, ADDR ps .ELSE invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret .ENDIF xor eax,eax ret
WndProc endp
end start
Анализ:
invoke CreateFont,24,16,0,0,400,0,0,0,OEM_CHARSET,\ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\ DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\ ADDR FontName
CreateFont создает логический фонт, который наиболее близок к данным параметрам и доступным данным фонта. Эта функция имеет больше параметров, чем любая другая в Windows. Она возвращает хэндл логического фонта, который можно выбрать функцией SelectObject. Мы в подробностях обсудим ее параметры.
CreateFont proto nHeight:DWORD,\ nWidth:DWORD,\ nEscapement:DWORD,\ nOrientation:DWORD,\ nWeight:DWORD,\ cItalic:DWORD,\ cUnderline:DWORD,\ cStrikeOut:DWORD,\ cCharSet:DWORD,\ cOutputPrecision:DWORD,\ cClipPrecision:DWORD,\ cQuality:DWORD,\ cPitchAndFamily:DWORD,\ lpFacename:DWORD
nHeight - желаемая высота символов. Hоль значит использовать pазмеp по умолчанию.
nWidth - желаемая ширина символов. Обычно этот параметр равен нулю, что позволяет Windows подобрать ширину соответственно высоте. Однако, в нашем примере, дефаултная ширина делает символы нечитабельными, поэтому я установил ширину равную 16.
nEscaрement - указывает ориентацию вывода следующего символа, относительно предыдущего в десятых градусов. Как правило его устанавливают в 0. Установка в 900 вынуждает идти все символы снизу вверх, 1800 - справа налево, 2700 - сверху вниз.
nOrientation - указывает насколько символ должен быть повернут в десятых градусов. 900 - все символы будут "лежать" на спине, и далее по аналогии с предыдущим параметром.
nWeight - устанавливает толщину линии. Windows определяет следующие размеры:
- FW_DONTCARE equ 0
- FW_THIN equ 100
- FW_EXTRALIGHT equ 200
- FW_ULTRALIGHT equ 200
- FW_LIGHT equ 300
- FW_NORMAL equ 400
- FW_REGULAR equ 400
- FW_MEDIUM equ 500
- FW_SEMIBOLD equ 600
- FW_DEMIBOLD equ 600
- FW_BOLD equ 700
- FW_EXTRABOLD equ 800
- FW_ULTRABOLD equ 800
- FW_HEAVY equ 900
- FW_BLACK equ 900
Вышеприведенное описание, ни в коем случае, не является исчерпывающим. Вам следует обратиться к вашему Win32 API Справочнику за деталями.
invoke SelectObject, hdc, eax mov hfont,eax
После получения хэндла логического фонта, мы должны выбрать его в контексте устройства, вызвав SelectObject. Функция устанавливает новые GDI объекты, такие как перья, кисти и фонты контекст устройства, используемые GDI функциями. SelectObjet возвращает хэндл замещенного объекта в eax, который нам следует сохранить для будущего вызова SelectObject. После вызова SelextObject любая функция вывода текста будет использовать фонт, который мы выбрали в данном контексте устройства.
RGB 200,200,50 invoke SetTextColor,hdc,eax RGB 0,0,255 invoke SetBkColor,hdc,eax
Используйте макрос RGB, чтобы создать 32-битное RGB значение, которое будет использоваться функциями SetColorText и SetBkColor.
invoke TextOut,hdc,0,0,ADDR TestString,SIZEOF TestString
Вызываем функцию TextOut для отрисовки текста на клиентской области экрана. Будет использоваться ранее выбранные нами фонт и цвет.
invoke SelectObject,hdc, hfont
После этого мы должны восстановить старый фонт обратно в данном контексте устройства. Вам всегда следует восстанавливать объект, который вы заменили.
[C] Iczelion, пер. Aquila.