Iczelion’s tutorial N°27 |
||
Data |
by "Death_Reaver" |
|
21/06/2005 |
Published by Quequero |
|
Se tutto il mondo va a donne… |
Armato di santa pazienza hai fatto un ottimo lavoro, grazie! |
Unisciti anche tu! |
.... |
Home page (se presente):NADA E-mail: [email protected] Nick, UIN, canale IRC/EFnet frequentato |
.... |
Difficoltà |
( )NewBies (*)Intermedio (*)Avanzato ( )Master |
|
Introduzione |
Continua la traduzione dei tutorial di Iczelion…
Per domande, chiarimenti e tutto quello che volete sapere sono sempre disponibile. La mia mail è [email protected]
Tools usati |
ALLEGATO (codice sorgente + eseguibile già compilato)
MASM32 v.8 sp1 (nella sezione tools)
RadAsm (IDE perfetto per programmare in asm)
Notizie sul programma |
In questo tutorial impareremo come si crea e usa un tooltip.
PS. NTD = nota del traduttore
Essay |
TEORIA:
Un tooltip è una piccola finestra rettangolare che è mostrata quando il puntatore del mouse sta su un'area specifica. Una finestra tooltip contiene del testo che il programmatore vuole che sia mostrato. In questo caso, un tooltip ha lo stesso ruolo della status-bar ma sparisce quando l'utente clicka o muove il mouse fuori dall'area designata. Probabilmente sei abituato a vedere i tooltip associati ai pulsanti di una toolbar. Quei tooltip sono create automaticamente con la toolbar. Se vuoi i tooltips per altri controlli/finestre hai bisogno di crearli da te. Adesso che sai che è un tooltip, vediamo come crearlo e usarlo. i principali passi sono:
1)Creare un controllo tooltip con CreateWindowsEx
2)Definire una regione che tooltip controllerà circa i movimenti del puntatore del mouse
3)Registrare e passare la regione al tooltip
4)Controllare i messaggi del mouse sul tooltip. (questo passo può servire farlo subito, dipende dal metodo usato per prendere i messaggi)
Esamineremo ogni passo in seguito.
Creazione Del Tooltip
Il tooltip è un controllo comune. Per questo devi chiamare InitCommonControls da qualche parte nel tuo codice cosicché MASM linkerà il tuo programma con comctl32.dll. I controlli tooltip si creano con CreateWindowEx. La situazione sarà come questa:
.data
TooltipClassName db "Tooltips_class32",0
....
invoke InitCommonControls
invoke CreateWindowEx,NULL,ADDRTooltipClassName,NULL,TIS_ALWAYSTIP,CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL
Notare lo stile TIS_ALWAYSTIP. Questo stile specifica che il tooltip sarà mostrato quando il puntatore del mouse sarà sull'area designata, fregandosene (rende meglio il concetto. NTD) dello stato attuale della finestra che contiene tale area. Se uso questo flag, quando metti il puntatore del mouse sull'area registrata(al tooltip), il tooltip apparirà, anche se la finestra puntata dal mouse è inattiva. Non c'è bisogno di includere i stili WS_POPUP e WS_EX_TOOLWINDOW dentro CreateWindowEx perchè la windows-procedure del tooltip li aggiunge automaticamente. Inoltre non serve specificare le coordinate e la grandezza del tooltip: il tooltip aggiusterà tali valori automaticamente per mostrare interamente il testo contenuto in esso e perciò li riempiamo con CW_USEDEFAULT in tutti e 4 i parametri.
Specificare ll "tool" (attrezzo, NTD)
Il tooltip è creato ma non è mostrato immediatamente. Noi vogliamo che il tooltip sia mostrato quando il puntatore del mouse punta in una qualche area. Adesso è arrivato il momento di specificare tale area. Questa area è chiamata "tool". Un tool è un'area rettangolare della client area di una finestra che il tooltip controllerà per verificare se è presente il cursore del mouse. Se il cursore punta al tool, la finestra di tooltip apparirà. L'area rettangolare può coprire l'intera client-area o solo una parte. Per questo motivo, possiamo dividere i tool in due tipi: uno che è implementato come una finestra e l'altro è implementato come un'area rettangolare della client-area di una finestra. Entrambi trovano applicazioni. Il tool che copre l'intera area di una finestra è perlopiù usato con controlli come button, editbox e così via. In questo caso non devi specificare le coordinate del tool, poiché questo coprirà l'intera client-area. Il tool che si basa su una zona rettangolare sulla client-area è utile quando vuoi dividere la client-area in tante "regioni" senza usare child-windows (finestre, controlli NTD). Con questo tipo di tool devi specificare le coordinate dell'angolo superiore sinistro e dimensioni del tool (altezza e larghezza). Il tool viene specificato con la struttura TOOLINFO che ha la seguente definizione:
TOOLINFO STRUCT
cbSize DWORD ?
uFlags DWORD ?
hWnd DWORD ?
uId DWORD ?
rect RECT <>
hInst DWORD ?
lpszText DWORD ?
lParam LPARAM ?
TOOLINFO ENDS
Nome Campo |
Spiegazione |
cbSize |
La grandezza della struttura TOOLINFO. DEVI riempire questo membro. Windows non segnalerà errori se questo membro non è riempito a dovere ma riceverà strani, indicibili risultati |
uFlag |
I flag che specificano le caratteristiche del tool. Questo valore può essere una combinazione dei valori sottostanti: · TTF_IDISHWND "ID is hWnd" (l'ID è l'hWnd, NTD). Se viene impostato, segnifica che vuoi che il tool copra tutta la client-area(primo tipo). Se usi questo flag, DEVI riempire il membro uID della struttura con l'handle della finestra che vuoi utilizzare. Se non lo usi, significa che il tool coprirà una zona della client-area(secondo tipo). In questo caso devi riempire il membro rect con la deimenzione della zona. · TTF_CENTERTIP normalmente il tooltip apparirà a destra e sotto il cursore del mouse. Se usi questo flag, il tooltip apparirà direttamente sotto il tool e sarà centrato secondo la posizione del mouse. · TTF_RTLREADING questo flag è inutile se il tuo programma non è designato specificatamente persistemi arabici o ebrei. Questo flag mostra il testo del tooltip leggendo il testo da destra a sinstra. Sugli altri sistemi non funziona · TTF_SUBCLASS se usi questo flag, dici al tooltip di subclassare la finestra su cui è il tool cosicchè possa intercettare i messaggi del mouse che sono mandati alla finestra. E' un flag molto utile. Se non lo sui dovrai fare più lavoro per mandare i messaggi del mouse al tooltip. |
hWnd |
L'Handle della finestra che contiene il tool. Se però setti il flag TTF_IDISHWND questo campo è ignorato poiché Windows userà il valore nel membro uId come handle della finestra. Devi riempire questo campo se:
|
uId |
Questo campo può avere due significati, dipende se il membro uFlags contiene il flag TTF_IDISHWND
|
rect |
Una struttura RECT che contiene le dimensioni del tool. Questa struttura definisce il rettangolo relativo all'angolo superiore sinistro della client-area della finestra indicata dal membro hWnd. In poche parole, devi riempire questa struttura se vuoi che il tool copra solo una parte della client-area. Il tooltip ignorerà questo membro se è specificato il flag TTF_IDISHWND (cioè se vuoi che il tool copra tutta la client-area). |
hInst |
L' hInstance-handle del luogo contenente la stringa che sarà usata come testo del tooltip se il valore in lpszText specifica l'ID della stringa. Può confondere: leggi prima la spiegazione di lpszText e capirai a che serve questo campo. Il tooltip ignora questo campo se lpszText non contiene l'ID di una stringa. |
lpszText |
Questo campo può avere molti valori:
|
(maledette tabelle NTD)
Per ricapitolare, devi riempire la struttura TOOLINFO prima di mandarla al tooltip. Questa struttura descrive le caratteristiche del tool.
Associare il tool al controllo tooltip
Dopo aver riempito la struttura TOOLINFO, devi inviarla al tooltip. Un tooltip può servire molti tool perciò di solito non è necessario creare più di un tooltip per finestra. Per associare un tool con un controllo tooltip, devi inviare il messaggio TTM_ADDTOOL al tooltip. wParam non è usato e lParam deve contenere l'indirizzo della struttura TOOLINFO che vuoi associare.
;----------------------
;piccolo esempio
;----------------------
.data?
ti TOOLINFO <>
.......
.code
.......
<fill the TOOLINFO structure>
.......
invoke SendMessage, hwndTooltip, TTM_ADDTOOL, NULL, addr ti
;---------------------
SendMessage restituirà TRUE se l'associamento è riuscito, altrimenti FALSE
Puoi dis-associare il tool inviando il messaggio TTM_DELTOOL al tooltip
Controllare i messaggi del mouse sul tooltip
Quando il passo precedente è stato completato, il tooltip conosce quale area deve monitorare per controllare se avvengono messaggi dal mouse e quale testo deve visualizzare una volta apparso. L'unica cosa che manca è il "grilletto" per farlo partire. Facciamo un esempio: L'area specificata dal tool è sulla client-area dell'altra finestra. Come può il tooltip intercettare i messaggi del mouse destinati a quella finestra? Ha bisogno di fare un pò di ordine in modo che possa misurare la quantità di tempo in cui il cursore del mouse punta sul tool e, quando passa questa quantità di tempo, il tooltip apparirà. Ci sono due metodi per riuscire nell'impresa, uno che richiede la collaborazione della finestra che contiene il tool e l'altra senza la collaborazione da parte della finestra.
(per capire meglio, vi consiglio di guardare l'esempio, NDT)
WM_LBUTTONDOWN
WM_MOSEMNOVE
WM_LBUTTONUP
WM_RBUTTONDOWN
WM_MBUTTONDOWN
WM_RBUTTONUP
WM_MBUTTONUP
tutti gli altri sono ignorati. Per questo nella window-procedure della finestra che contiene il tool, ci deve essere un "switch" che fa qualcosa del genere:
WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
.......
if uMsg==WM_CREATE
.............
elseif uMsg==WM_LBUTTONDOWN || uMsg==WM_MOUSEMOVE || uMsg==WM_LBUTTONUP || uMsg==WM_RBUTTONDOWN || uMsg==WM_MBUTTONDOWN || uMsg==WM_RBUTTONUP || uMsg==WM_MBUTTONUP
invoke SendMessage, hwndTooltip, TTM_RELAYEVENT, NULL, addr msg
..........
Ce l'abbiamo fatta. A questo punto il tooltip è pienamente funzionante. Ci sono un sacco di messaggi utili relativi al tooltip che dovresti conoscere.
ESEMPIO:
L'esempio seguente è una semplice dialog box con due pulsanti. La client-area è divisa in quattro parti: in alto a sinistra, in altro a destra, in basso a sinistra e in basso a destra. Ogni area è considerata come un tool con il suo testo di tooltip. I due pulsanti hanno i loro testi per il tooltip
.386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\user32.inc include \masm32\include\comctl32.inc includelib \masm32\lib\comctl32.lib includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD EnumChild proto :DWORD,:DWORD SetDlgToolArea proto :DWORD,:DWORD,:DWORD,:DWORD,:DWORD .const IDD_MAINDIALOG equ 101 .data ToolTipsClassName db "Tooltips_class32",0 MainDialogText1 db "This is the upper left area of the dialog",0 MainDialogText2 db "This is the upper right area of the dialog",0 MainDialogText3 db "This is the lower left area of the dialog",0 MainDialogText4 db "This is the lower right area of the dialog",0 .data? hwndTool dd ? hInstance dd ? .code start: invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,hInstance,IDD_MAINDIALOG,NULL,addr DlgProc,NULL invoke ExitProcess,eax
DlgProc proc hDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD LOCAL ti:TOOLINFO LOCAL id:DWORD LOCAL rect:RECT .if uMsg==WM_INITDIALOG invoke InitCommonControls invoke CreateWindowEx,NULL,ADDR ToolTipsClassName,NULL,\ TTS_ALWAYSTIP,CW_USEDEFAULT,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInstance,NULL mov hwndTool,eax mov id,0 mov ti.cbSize,sizeof TOOLINFO mov ti.uFlags,TTF_SUBCLASS push hDlg pop ti.hWnd invoke GetWindowRect,hDlg,addr rect invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText1,id,addr rect inc id invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText2,id,addr rect inc id invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText3,id,addr rect inc id invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText4,id,addr rect invoke EnumChildWindows,hDlg,addr EnumChild,addr ti .elseif uMsg==WM_CLOSE invoke EndDialog,hDlg,NULL .else mov eax,FALSE ret .endif mov eax,TRUE ret DlgProc endp
EnumChild proc uses edi hwndChild:DWORD,lParam:DWORD LOCAL buffer[256]:BYTE mov edi,lParam assume edi:ptr TOOLINFO push hwndChild pop [edi].uId or [edi].uFlags,TTF_IDISHWND invoke GetWindowText,hwndChild,addr buffer,255 lea eax,buffer mov [edi].lpszText,eax invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,edi assume edi:nothing ret EnumChild endp
SetDlgToolArea proc uses edi esi hDlg:DWORD,lpti:DWORD,lpText:DWORD,id:DWORD,lprect:DWORD mov edi,lpti mov esi,lprect assume esi:ptr RECT assume edi:ptr TOOLINFO .if id==0 mov [edi].rect.left,0 mov [edi].rect.top,0 mov eax,[esi].right sub eax,[esi].left shr eax,1 mov [edi].rect.right,eax mov eax,[esi].bottom sub eax,[esi].top shr eax,1 mov [edi].rect.bottom,eax .elseif id==1 mov eax,[esi].right sub eax,[esi].left shr eax,1 inc eax mov [edi].rect.left,eax mov [edi].rect.top,0 mov eax,[esi].right sub eax,[esi].left mov [edi].rect.right,eax mov eax,[esi].bottom sub eax,[esi].top mov [edi].rect.bottom,eax .elseif id==2 mov [edi].rect.left,0 mov eax,[esi].bottom sub eax,[esi].top shr eax,1 inc eax mov [edi].rect.top,eax mov eax,[esi].right sub eax,[esi].left shr eax,1 mov [edi].rect.right,eax mov eax,[esi].bottom sub eax,[esi].top mov [edi].rect.bottom,eax .else mov eax,[esi].right sub eax,[esi].left shr eax,1 inc eax mov [edi].rect.left,eax mov eax,[esi].bottom sub eax,[esi].top shr eax,1 inc eax mov [edi].rect.top,eax mov eax,[esi].right sub eax,[esi].left mov [edi].rect.right,eax mov eax,[esi].bottom sub eax,[esi].top mov [edi].rect.bottom,eax .endif push lpText pop [edi].lpszText invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,lpti assume edi:nothing assume esi:nothing ret SetDlgToolArea endp end start |
ANALISI:
Dopo che la finestra principale è stata creata, creiamo il tooltip con CreateWindowEx
invoke InitCommonControls invoke CreateWindowEx,NULL,ADDR ToolTipsClassName,NULL,\ TTS_ALWAYSTIP,CW_USEDEFAULT,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInstance,NULL mov hwndTool,eax |
Dopodichè, andiamo avanti definendo 4 tool, uno per ogni angolo della dialog-box
mov id,0 ; usato come ID del tool mov ti.cbSize,sizeof TOOLINFO mov ti.uFlags,TTF_SUBCLASS ; dice al tooltip di subclassare la dialog-box push hDlg pop ti.hWnd ; handle della finestra che contiene il tool invoke GetWindowRect,hDlg,addr rect ; otteniamo le dimenzioni della client-area invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText1,id,addr rect |
Inizializziamo i membri della struttura TOOLINFO. Notare che se vogliamo dividere la client-area in 4 parti, abbiamo bisogno della dimensioni della client-area. Per questo chiamiamo GetWindowRect. Non vogliamo rilasciare i messaggi del mouse al tooltip a mano, perciò specifichiamo il flag TIF_SUBCLASS. SetDlgToolArea è una funzione che calcola "l'area rettangolare" di ogni tool e registra il tool al tooltip. Non andrò nei dettagli riguardo il calcolo, basti sapere che divide la client-area in 4 parti uguali. Quindi invia il messaggio TTM_ADDTOOL al tooltip passandogli l'indirizzo della struttura TOOLINFO in lParam.
invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,lpti |
Dopo che tutti i 4 tool sono registrati, possiamo andare avanti con i pulsanti sulla dialog-box. Possiamo gestire ogni pulsante tramite l'ID ma sarebbe noioso. Invece, useremo l'API EnumChildWindows per "numerare" tutti i controlli sulla dialog-box e registrarli al tooltip. EnumChildWindows ha la seguente sintassi:
EnumChildWindows proto hWnd:DWORD, lpEnumFunc:DWORD, lParam:DWORD
hWnd è l'handle della parent-window. lpEnumFunc è l'indirizzo della funzione EnumChildProc che sarà chiamata per ogni controllo numerato. lParam è il valore application-defined che sarà passato alla funzione EnumChildProc.
EnumChildProc ha la seguente sintassi:
EnumChildProc proto hwndChild:DWORD, lParam:DWORD
hwndChild è l'handle del controllo numerato da EnumChildWindows. lParam è lo stesso passato a EnumChildWindows.
Nel nostro esempio chiamiamo EnumChildWindows così:
invoke EnumChildWindows,hDlg,addr EnumChild,addr ti |
Passiamo l'indirizzo della struttura TOOLINFO in lParam perchè vogliamo registrare ogni controllo al tooltip nella funzione EnumChild. Se non usiamo questo metodo, dobbiamo dichiarare ti come variabile globale e potrebbero presentarsi bugs.
Quando chiamiamo EnumChildWindows, Windows numererà i control presenti nella dialog-box e chiamerà la funzione EnumChildProc una volta per ogni controllo numerato. Nel nostro caso ci sono due controlli e quindi la EnumChildProc verrà chiamata 2 volte. (nell'esempio l'EnumChildProc è EnumChild NTD)
La funzione EnumChild riempie i membri importanti della struttura TOOLINFO e quindi registra il tool al tooltip
EnumChild proc uses edi hwndChild:DWORD,lParam:DWORD LOCAL buffer[256]:BYTE mov edi,lParam assume edi:ptr TOOLINFO push hwndChild pop [edi].uId ; usiamo l’intera client-area come tool or [edi].uFlags,TTF_IDISHWND invoke GetWindowText,hwndChild,addr buffer,255 lea eax,buffer ; usiamo il tsto della finestra come testo del tooltip mov [edi].lpszText,eax invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,edi assume edi:nothing ret EnumChild endp |
Notare che in questo caso usiamo un tipo diverso di tool: quello che copre l'intera client-area. Percui abbiamo bisogno di riempire il membro uID con l'handle della finestra che contiene il tool. Inoltre va settato il flag TTF_IDISHWND nel membro uFlags.
DEATH_REAVER
Note finali |
Un saluto e un grazie a tutti i compagni di cracking e coding
Disclaimer |
Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.
Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.