Страница: 1 |
|
Вопрос: Прошу помощи у знатоков МАСМа
|
Добавлено: 09.12.06 17:23
|
|
Автор вопроса: VerhoLom
|
Прошу громко не смеяться, в тонкостях ассемблирования пока не разобрался, но пытаюсь. Пытаюсь изучить МАСМ. Использую МАСМ от Хатча. Написал на нем пока всего 2 безделушки: индикатор раскладки, выводящий флажок раскладки клавиатуры в трее (правда, идея не моя, а просто ради изучения языка решил переписать на МАСМе имеющуюся программу на LCC, которая РусЛатом называется - надо же с чего-то начинать) и проблем особых не возникло.
Потом шеф где-то услыхал, что есть программа, которая на кнопке ПУСК вместо вот этого слова выводит время, вследствии чего экономится пространство на панели задач. Икать ее, естественно, никто не хочет, а этот никто хочет, чтобы программа была написана мной. Я понимаю, штука несложная, я ее на VB за 2 часа сделал, а вот потом решил попробовать ради интереса то же самое на МАСМе переписать. Вот здесь и возникли проблемы.
Кнопочка ПУСК, оказывается, перерисовывается при смене обоев на рабочем столе, смене темы и системных цветов. Был выбран вариант, при котором создается невидимое окошко и отслеживаются сообщения, приходящие ему (WM_SYSCOLORCHANGE и т. д.), а в таймере каждые 500 мс. проверять текущую минуту времени и сравнивать ее с запомненной предыдущей. Если они равны, то ничего не делаем, если нет - то читаем системное время и, соответственно, выводим его на кнопку ПУСК. Если произошло событие, при котором кнопочка пуск перерисовывается, то просто меняется значение запомненной минуты на 65 (число от фонаря) и при срабатывании таймера время будет выведено на кнопку. Проще, в принципе, некуда... Но возникла проблема: мне не удается зарегистрировать фоновое окошко. Вот недописанный исходник (споткнулся на регистрации окна):
;;========================================================
.486
;;##########################################################################
.model flat,stdcall
option casemap:none
;;##########################################################################
WinMain Proto
WndProc Proto :DWORD, :DWORD, :DWORD, :DWORD
;;##########################################################################
@GetMsg MACRO Mes:REQ, v:REQ, inst:REQ, wnd:REQ
Local mm, szRet
push eax
.data
mm db Mes,":",0Dh,0Ah,"GetLastError = 0x%02X",0Dh,0Ah,"hInstance = 0x%02X",0Dh,0Ah,"hWnd = 0x%02X",0
szRet db 0
align 4
.code
invoke wsprintf,addr szRet,addr mm,v,inst,wnd
pop eax
exitm <addr szRet>
EndM
;;##########################################################################
include windows.inc
include user32.inc
include kernel32.inc
;;##########################################################################
includelib user32.lib
includelib kernel32.lib
;;##########################################################################
.data
szClass db "start_button_time_wnd_class",0
szName db "Часы в кнопке ПУСК.",0
szWord db "%02d",0
szTimeRet db "%s:%s",0
;;##########################################################################
.data?
hInst dd ?
hWin dd ?
bOth db ?
;;##########################################################################
.code
_main:
invoke GetModuleHandle,NULL
mov hInst,eax
invoke WinMain
invoke ExitProcess,NULL
;;##########################################################################
WinMain PROC
Local wc:WNDCLASSEX, msg:MSG
;;invoke RtlFillMemory,addr wc,SizeOf wc,0
mov wc.cbSize,SizeOf WNDCLASSEX
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
mov wc.hbrBackground,COLOR_WINDOW
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
push hInst
pop wc.hInstance
mov wc.lpfnWndProc,offset WndProc
mov wc.lpszClassName,offset szClass
mov wc.lpszMenuName,NULL
mov wc.style,CS_VREDRAW or CS_HREDRAW
invoke RegisterClassEx,addr wc
invoke CreateWindowEx,0,addr szClass,addr szName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInst,NULL
mov hWin,eax
.If hWin == NULL
invoke GetLastError
invoke MessageBox,NULL,@GetMsg("Произошла ошибка создания фонового окна",eax,hInst,hWin),NULL,MB_ICONERROR+MB_TASKMODAL
ret
.EndIf
invoke ShowWindow,hWin,SW_SHOW
invoke UpdateWindow,hWin
.While 1
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:DWORD, uMsg:DWORD, wPrm:DWORD, lPrm:DWORD
.If uMsg == WM_CREATE
mov eax,TRUE
ret
.EndIf
xor eax,eax
Ret
WndProc EndP
end _main
;;========================================================
Окно не создается...
Отладчук (OllyDbg) показал такую картину, что сбой идет при регистрации окна (см. вложения) - возникает ошибка ERROR_FILE_NOT_FOUND, т. е. нельзя найти хэндл исполняемого модуля программы, но invoke GetModuleHandle,NULL возвращает 00400000, т. е. хэндл модуля (см. второе вложение).
Я ради интереса прогнал в отладчике программу с выводом раскладки клавиатуры и, что интересно, хэндл модуля возвращается тот же, хотя программа может быть загружена в 2-... экземплярах. При этом все работает. Получается, что я что-то упускаю при заполнении структуры WNDCLASSEX. Попоробовал запустить экзешник на других компьютерах, так там та же история - выскакивает окошко с сообщением о той же ошибке (правда, на одном из них окно не создалось, а вот GetLastError вернул 0).
Такая вот беда... Если не сложно, подскажите, в чем ошибка? Может, я не так заполняю структуру окна?
Ответить
|
Номер ответа: 2 Автор ответа: JMP
Вопросов: 6 Ответов: 171
|
Профиль | | #2
|
Добавлено: 09.12.06 19:17
|
Сильно не вникал, но первое что увидел
invoke CreateWindowEx,0,addr szClass,addr szName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInst,NULL
АПИ CreateWindowEx не имеет таких констант как CW_xxx
Это константы класса. Кстати их очень легко различать
WS- windows style
CW- class window
И... почему вы их(стилевые константы) все через запятую?
Их надо по И(+) это же один параметр
Ответить
|
Номер ответа: 5 Автор ответа: JMP
Вопросов: 6 Ответов: 171
|
Профиль | | #5
|
Добавлено: 10.12.06 13:22
|
Вообще-то это координаты по умолчанию
Тьфу, @#$%^&* блин, совсем ослеп
CS-Class style
сорри за дезу
sne, good catch
vbman,
Поставте в виндовс процедуре обработку выхода(WM_DESTROY),а то окошко будет закрываться, а процесс останется в памяти работать
WndProc PROC hWnd:DWORD, uMsg:DWORD, wPrm:DWORD, lPrm:DWORD
.If uMsg == WM_CREATE
mov eax,TRUE
ret
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
mov eax, 0
ret
.EndIf
invoke DefWindowProc ,hWnd, uMsg, wPrm, lPrm
Ret
WndProc EndP
Ответить
|
Номер ответа: 9 Автор ответа: JMP
Вопросов: 6 Ответов: 171
|
Профиль | | #9
|
Добавлено: 21.12.06 18:07
|
Ну если не доверяете, то вот полностью рабочий код вашей программы:
;;========================================================
.486
;;##########################################################################
.model flat,stdcall
option casemap:none
;;##########################################################################
WinMain Proto
WndProc Proto :DWORD, :DWORD, :DWORD, :DWORD
;;##########################################################################
@GetMsg MACRO Mes:REQ, v:REQ, inst:REQ, wnd:REQ
Local mm, szRet
push eax
.data
mm db Mes,":",0Dh,0Ah,"GetLastError = 0x%02X",0Dh,0Ah,"hInstance = 0x%02X",0Dh,0Ah,"hWnd = 0x%02X",0
szRet db 0
align 4
.code
invoke wsprintf,addr szRet,addr mm,v,inst,wnd
pop eax
exitm <addr szRet>
EndM
;;##########################################################################
include c:\masm32\include\windows.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\kernel32.inc
;;##########################################################################
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
;;##########################################################################
.data
szClass db "start_button_time_wnd_class",0
szName db "Часы в кнопке ПУСК.",0
szWord db "%02d",0
szTimeRet db "%s:%s",0
;;##########################################################################
.data?
hInst dd ?
hWin dd ?
bOth db ?
;;##########################################################################
.code
_main:
invoke GetModuleHandle,NULL
mov hInst,eax
invoke WinMain
invoke ExitProcess, eax ; NULL
;;##########################################################################
WinMain PROC
Local wc:WNDCLASSEX, msg:MSG
;;invoke RtlFillMemory,addr wc,SizeOf wc,0
mov wc.cbSize,SizeOf WNDCLASSEX
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
mov wc.hbrBackground,COLOR_WINDOW
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
push hInst
pop wc.hInstance
mov wc.lpfnWndProc,offset WndProc
mov wc.lpszClassName,offset szClass
mov wc.lpszMenuName,NULL
mov wc.style,CS_VREDRAW or CS_HREDRAW
invoke RegisterClassEx,addr wc
invoke CreateWindowEx,0,addr szClass,addr szName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInst,NULL
mov hWin,eax
.If hWin == NULL
invoke GetLastError
invoke MessageBox,NULL,@GetMsg("Произошла ошибка создания фонового окна",eax,hInst,hWin),NULL,MB_ICONERROR+MB_TASKMODAL
ret
.EndIf
invoke ShowWindow,hWin,SW_SHOW
invoke UpdateWindow,hWin
.While 1
;mLoop:
;invoke PeekMessage, addr msg, hWin, 0, 0, PM_NOREMOVE ;IF PeekMessage(msg, hWnd, 0, 0, %PM_NOREMOVE) THEN
;test eax,eax
;jz mLoop
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:DWORD, uMsg:DWORD, wPrm:DWORD, lPrm:DWORD
.If uMsg == WM_CREATE
mov eax,TRUE
ret
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
mov eax, 0
ret
.EndIf
invoke DefWindowProc ,hWnd, uMsg, wPrm, lPrm
Ret
WndProc EndP
end _main
;;========================================================
Ответить
|
Страница: 1 |
Поиск по форуму