Greetings,

I have a question. Lets say that I have some controls on a screen and I want to intercept when anyone clicks on any of the controls. There can be x number of controls. How do I do this?

For example, I want to make a flow chart program. When the objects are clicked, I want to know and act accordingly so a flow chart can be designed intelligently.


Thanks,
_Shawn
Posted on 2001-11-02 10:37:31 by _Shawn
Hi,

I'm not sure if I understand it correct.
For example, if the control is a Listview,
proceed th WM_NOTIFIY message for a Click
inside the control.
On a Listview the item text is avaible via a
few API's.

Hm, I have no expierience with flow charts.

bye


TD
Posted on 2001-11-02 10:53:29 by Test Department
Basically it's this, any control that's in a particular window, I need to have a handler know that the control was clicked and handle it accordingly. Each flow chart object is a window, a custom control if you will, could be a button, too. Nonetheless, it shouldn't matter what control it is, I just want to know if it was clicked and handle it. Because each flowchart object needs to have a list of properties and options and each flow chart object is different.

It would be similar to if I had a random number of buttons and combo boxes and list boxes but I need to know if it was clicked and handle them accordingly. A flowchart object is nothing more than a child window.


Thanks,
_Shawn
Posted on 2001-11-02 10:58:37 by _Shawn
Ho,
If WM_NOTIFY is not usuable.
After creating the flowchart windows,
proceeding the 'WM_LButtonDown' message,
using API 'GetWindowRect', 'PtInRect' ...
Hm, a cheap solution.

Do WM_NOTIFY not work with BUTTONS, EDIT ... ?

I hope I don't start more questions than offer
an answer.


TD
Posted on 2001-11-02 11:16:33 by Test Department
Will WM_LBUTTONUP not do it?
I'm not sure if you can click down over one button,
keep holding the button down moving to another widget,
then release over that one,
and not get the WM_LBUTTONUP on the second (unwanted) control.

Also if you hold down the WM_LBUTTONDOWN will it apply to all controls it passes over while down?

Any-who here's my super safe way:


;On WM_LBUTTONDOWN
cmp OnDown, 0
jne @f
;Not been pressed on another control!
;So we continue
mov OnDown, hThisControl
@@:
;The end!

;----------------------------------------
;On WM_LBUTTONUP
mov eax, OnDown
cmp eax, hThisControl
jne @F
;They match, it must be a click (button up matches button down)
;Do stuff!
@@:
mov OnDown, 0
;Clear OnDown ready for the next WM_LBUTTONDOWN

;The end!


OnDown needs to be a globally accessable variable.

Mirno
Posted on 2001-11-02 11:19:15 by Mirno
Is it possible to hook all the controls created? Because I need to provide a way to supply controls via plugins, as well. I can't have them all predefined.


Thanks,
_Shawn
Posted on 2001-11-02 11:25:57 by _Shawn
Hoho,
Yes Mirno, I think it works great. It depends on the way you wonna handle all.

Hey Shawn,
I'm near sure it is possible to use WM_NOTIFY
with static windows where you can display an
image or text .

As I know, a flowchart is displaying icons and/or
text.

Hook, sorry non knowledge.
Iczelion wrote something ...

All I remember ... is that we must manage several
messages to control different 'controls'.


TD
Posted on 2001-11-02 11:55:41 by Test Department
Yes, for the most part it would just be some sort of shape with another transparent edit control showing editable text in the shape but in the case of UML, it would be a listbox. Then there are lines and arcs and other windows that are clickable and draggable and movable and then there would be the custom shapes that aren't pre-defined by the app but are plugged into the program.


Thanks,
_Shawn
Posted on 2001-11-02 12:32:37 by _Shawn
Wow,

That is to much for me.
Confusion, I think I'm not a great help.
You need the handle to all windows created ?
Use an array or a table and reference to that
in a loop or elseware.
Doing it that way you can manage all controls,
via a window handele pointer.

None knowledge about plugins. Sorry ...

TD
Posted on 2001-11-02 12:51:33 by TeST Department
In the API docs, you can find that the parent window of any control will receive WM_NOTIFY messages. Usually, the message also has a pointer to a NMHDR tructure, from which you can get (from pointer.code) the actual notification. However, if your controls are buttons, you will also be able to pick up on the BN_CLICKED message, the ID will be in the loword of wParam (in the WM_COMMAND message) and the handle in lParam, so if you have stated either when creating the control, you'll be able to easily parse which was clicked. I have some snips of code that illustrate how to find this out, if you'd like it; just let me know,
Posted on 2001-11-02 16:20:50 by stevkoch
Yes, I am greatly interested...

BTW: I have a VB version, but I want to create my own independant version of a flow chart program that lets you type in psuedo-code and as you type, in real time, it generates the flow chart. It's an excellent Visio Add-In, but I want my own program so I can incorporate it into my own programs...


Thanks,
_Shawn
Posted on 2001-11-02 16:33:06 by _Shawn
Shawn,

The only reliable way I know of trapping mouse clicks globally in an app is to trap them in the main message loop. You will need to know the handles of the controls so you will probably need to use a global array to store the handles of any new windows you add.

When i do hot keys I manually trap them in the main message loop so they are available no matter what control has the focus.

Regards,

hutch@movsd.com
Posted on 2001-11-02 18:15:57 by hutch--
Hi again,

with this code snippet you can check controls,
that send a WM_NOTIFY message, for a Mouseclick.
I hope it is error free.



.Data
hWnd_maxNr dd 0 ;max. number of controls
hWnd_array dd 0,0,0 ;hWnd01, hWnd02, hWnd03 ...
ctrl_action dd 0,0,0 ;addr01, addr02, addr03 ...

.Code ;inside the window procedure
;=========================================================================
; WM_NOTIFY (value=4Eh) message received ?
; With a WM_NOTIFY message Windows gives you pointer to a NMHDR structure.
;-------------------------------------------------------------------------
WP1_uMsg_4Eh:
cmp eax,4Eh ;check if WM_NOTIFY message recieved
jne WP1_return ;if not goto label
;-------------------------------------------------------------------------
; The NMHDR structure contains information about a notification message.
; The POINTER to this structure is specified as lParam member of WM_NOTIFY.
; This POINTER is given to us with the WM_NOTIFY message by Windows.
; hwndFrom = [WP1_lParam+0] ;handle to control sending message
; idFrom = [WP1_lParam+4] ;identifier of control sending message
; code = [WP1_lParam+8] ;notification code
;-------------------------------------------------------------------------
mov ebx,WP1_lParam ;pointer to NMHDR struc, given by windows !
mov eax,[ebx+0] ;get the handle of the control sending msg.
mov ecx,hWnd_maxNr ;max number of controls
mov edx,OFFSET hWnd_array ;pointer to array with control handle
mov edi,OFFSET ctrl_action ;pointer to the code we like to perform
ControlLoop:
cmp eax,[edx] ;do control match an entry in the array ?
je ControlMatch ;then go
add edx,4 ;add 4 byte
add edi,4 ;add 4 byte
dec ecx ;check all entries in the array
jne ControlLoop ;loop
jmp WP1_return ;no match found
ControlMatch:
mov eax,[ebx+8] ;get the notification code
cmp eax,0FFFFFFFDh ;NM_DBLCLK, NMFIRST=0-0-3
jne WP1_return ;
mov eax,[edi] ;
call eax ;call function defined in ctrl_action array
jmp WP1_return ;end of code snippet



bye TD
Posted on 2001-11-03 04:44:35 by Test Department
Instead of looping arrays every user's click, why not to make these graphic objects a bit more self contained? You can allocate some memory for every control you create and fill it with usefull info such as ActionToPerform, ShapeType, ShapeColor, ShapeState (disabled, locked.... and so on). Then, after having created the child control, with a call to SetWindowLong with GWL_USERDATA index, add the pointer to the allocated and filled memory to the control itself:


LONG SetWindowLong(
HWND hWnd, // handle to window
int nIndex, // offset of value to set
LONG dwNewLong // new value
);

Where nIndex is GWL_USERDATA in this case.
Then, when you receive a WM_NOTIFY message with a call to GetWindowLong you retrieve the pointer to the memory previously allocated filled with info about the control:


LONG GetWindowLong(
HWND hWnd, // handle to window
int nIndex // offset of value to retrieve
);

Where nIndex is again GWL_USERDATA.
Posted on 2001-11-03 05:32:51 by LuHa
Hi LuHa,
sounds very good !

But in the moment I'm not sure about the
advantage and disadvantage of every method.

I'm interested and I will perform some tests in
the next weeks.

Thank you

TD
Posted on 2001-11-03 06:12:03 by Test Department
OK, Test Dept., let us known :).
Posted on 2001-11-03 07:20:16 by LuHa