· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.WIN32 —› Кнопка GDI+

Посл.отвђт Сообщенiе


Дата: Авг 23, 2003 20:15:52

Значит так: надумал я создать компонентик - кнопка на основе GDI+. Я в этом деле начинающий так что буду рад совету от Знающих как мне сделать следующее...

Надо чтобы кнопку можно было создать специальной функцией например CreateGdipButton proc hBrush, rect...

Мне в этом не понятно только одно: кнопка - это окно значит его создают так: RegisterClassEx + CreateWindowEx. Там есть процедура WndProc, обрабатывающая события от винды. Дак вот при создании нескольких кнопок адрес этой процедуры никуда не денется т.е. у всех кнопок будет один и тот же обработчик событий? Или как? Или я чтото напутал? А может для каждой кнопки свой тред создавать? Или как? Подскажите а...


Дата: Авг 23, 2003 22:57:40

Дак вот при создании нескольких кнопок адрес этой процедуры никуда не денется т.е. у всех кнопок будет один и тот же обработчик событий?
Естественно.

А может для каждой кнопки свой тред создавать?
Нет.

Лучше всего написать DLL.
DllEntry - DLL_PROCESS_ATTACH: заполнить WNDCLASSEX и вызвать RegisterClassEx. Не забудьте добавить CS_GLOBALCLASS в WNDCLASSEX.style. Иначе контрол не будет создаваться в пользовательском процессе (вне DLL).
DllEntry - DLL_PROCESS_DETACH: UnregisterClass

Скелет на MASM32:
.DATA
szClassName	db 'GdipButton',0

.DATA?
hInst		dd ?

.CODE
DllEntry PROC hInstance:DWORD,reason:DWORD,resvd:DWORD
LOCAL wc:WNDCLASSEX
 .IF reason == DLL_PROCESS_ATTACH
  mov wc.cbSize,SIZEOF WNDCLASSEX
  mov wc.style,CS_HREDRAW or CS_VREDRAW or CS_GLOBALCLASS
  mov wc.lpfnWndProc,OFFSET GdipButton
  mov eax,hInstance
  mov hInst,eax
  mov wc.hInstance,eax
  mov wc.lpszClassName,OFFSET szClassName
  xor eax,eax
  mov wc.hbrBackground,eax
  mov wc.cbClsExtra,eax
  mov wc.cbWndExtra,eax
  mov wc.hIcon,eax
  mov wc.hIconSm,eax
  mov wc.lpszMenuName,eax
  invoke LoadCursor,eax,IDC_ARROW
  mov wc.hCursor,eax
  invoke RegisterClassEx,ADDR wc
 .ELSEIF reason == DLL_PROCESS_DETACH
  invoke UnregisterClass,OFFSET szClassName,hInst
 .ENDIF
 mov eax,1
 ret
DllEntry ENDP

; Button callback (WndProc)
GdipButton PROC hWnd:DWORD,uMsg:DWORD,wP:DWORD,lP:DWORD
 mov eax,uMsg
 .IF eax == WM_PAINT
  ; Рисуем кнопку
  ; . . .
 .ELSEIF eax == WM_CREATE
  ; . . .
 .ELSEIF eax == WM_DESTROY
  ; . . .
 .ELSE
  invoke DefWindowProc,hWnd,uMsg,wP,lP
 .ENDIF
 ret
GdipButton ENDP

; DLL должна экспортировать хоть одну ф-цию
; Иначе её не прилинкуешь статически
myStub PROC
    ret
myStub ENDP
END DllEntry


Дата: Авг 24, 2003 07:26:05

Понял, спасибо! Я так уже делал, но вдруг както подругому можно.
Но тут другая проблема вылезает - в MSDN написано, что в GDI+ нельзя вызывать функцию GdiplusStartup, я так и не понял почему. Я пытался рисовать GDI+ом при помоши сабклассинга - хотел перехватить WM_ERASEBKGND, сообщение перехватил, а GDI+ не рисует. Мне кажется это связано, ведь все контролы находятся в DLL.


Дата: Авг 24, 2003 18:40:23

Ну сделал я эту штуку DLL-кой и получилось, что для разных кнопок вызывается один и тот же код и используются одни и те же данные. Т.е. вызов вот этого:
invoke CreateGdipButton,ADDR TestString1, hWnd, ADDR rectBut1
invoke CreateGdipButton,ADDR TestString2, hWnd, ADDR rectBut2
дает два абсолютно одинаковых окошка с текстом из TestString2. Ну короче как я и говорил.

Текст процедуры такой:
CreateGdipButton proc pText:DWORD, hWnd:DWORD, pRect:DWORD
LOCAL wc:WNDCLASSEX
invoke GetModuleHandle, NULL
mov hInstance,eax
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style,CS_HREDRAW+CS_VREDRAW+CS_DBLCLKS
mov wc.lpfnWndProc,OFFSET ButtonWndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ButtonClassName
mov wc.hIcon,NULL
mov wc.hIconSm,NULL
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc

mov edi,pRect
invoke CreateWindowEx,WS_EX_CLIENTEDGE,addr ButtonClassName,0,\
WS_CHILD or WS_VISIBLE,(RECT ptr [edi]).left,(RECT ptr [edi]).top,\
(RECT ptr [edi]).right, (RECT ptr [edi]).bottom,\
hWnd,0,hInstance,0
m2m pButtonText,pText
; mov hwndTextEdit,eax
ret
CreateGdipButton endp


Дата: Авг 24, 2003 18:53:14

profi_r
дает два абсолютно одинаковых окошка с текстом из TestString2
Так и должно быть, ведь переменная pButtonText одна на всю DLL :-) Текст нужно сохранять по отдельности для каждой кнопки. Хороший кандидат на роль буфера для этого текста -- это параметр lpWindowName ф-ции CreateWindowEx (у вас там ноль). Например:
invoke CreateWindowEx,WS_EX_CLIENTEDGE,\
       addr ButtonClassName,pText,\
       WS_CHILD or WS_VISIBLE,\
       (RECT ptr [edi]).left,(RECT ptr [edi]).top,\
       (RECT ptr [edi]).right,(RECT ptr [edi]).bottom,\
       hWnd,0,hInstance,0
; Потом в обработчике сообщений
; (на WM_PAINT, например):
invoke SendMessage,hButton,WM_GETTEXT,64,OFFSET strBuf
; Рисуем этот текст на кнопке


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.107