April 26, 2024, 05:56:47 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Detecting type of control

Started by Andy, October 21, 2016, 12:20:00 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

October 21, 2016, 12:20:00 AM Last Edit: October 21, 2016, 03:33:46 AM by Andy
I'm revisiting my Mouse over controls include file which detects if the mouse is over a control.

And I was wondering when you create a window with some controls e.g. buttons, check boxes, statics etc, if there was a way to detect what type of control it is - i.e. a button / checkbox etc.

I can easily change my include file so I can pass the type, but I was wondering if I could do this another way in IWB.

More specifically, I'm trying to work out the relationship between the height of  / position of each string in a list box and the height of the list box itself.

The help file states that the size of the font in points relates to nth fraction of 72. i.e. a font set to size 36 should be half an inch, and one set to 72 would be one inch.

If I set the list box font to 12, and the height of the list box to 72, I should be able to fit in 6 (72 / 12) strings.

But I can only fit 4 in, and the 4th is cut in half.

To work this out, do I have to factor in the users screen resolution? 

Thanks,
Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Egil

October 21, 2016, 05:12:02 AM #1 Last Edit: October 21, 2016, 05:14:43 AM by Egil
Not sure if this will help, but have you tried to use GETTEXTSIZE?


Egil
Support Amateur Radio  -  Have a ham  for dinner!

Andy

Egil,

That's a nice idea, but it doesn't work for me.

No matter what font size I use for the list box, the height doesn't change.

Getsize doesn't work either as this only returns the size of the entire list box.

Thanks for the suggestion.
Andy.

Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

I've just been trying:

SendMessage(win2, LB_GETITEMHEIGHT, 0, 0, 100)

Where win2 - window
and 100 the list box control ID.

This does change as you change the font size.

Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

October 21, 2016, 06:41:11 AM #4 Last Edit: October 21, 2016, 06:46:20 AM by Andy
I've managed a formula that seems to work (at least on my PC, and for different screen resolutions):

Using the command:
SendMessage(win2, LB_GETITEMHEIGHT, 1, 0, 100)

Returns the font size + 6

font 12 + 6 = 18
2 for the line + 2 down + 18 + 2 below the string = 24 (for the first string in the list box)
2 items 24 + 18 = 42
3 items 24 + 18 + 18 = 60 and so on...

font 10 + 6 = 16
2 for the line + 2 down + 16 + 2 below the string = 22 (for the first string in the list box)
2 items 22 + 16 = 38
3 items 22 + 16 + 16 = 54 and so on ...

So I think now, providing it works on the laptop too, I can use this formula to store that actual locations of each string in a list box as I know the whole list box co-ordinates (using my Mouse Over Controls include file).

But the question still remains, how can I detect which type of control the mouse is over? I can just add an extra parameter to:

MouseOverControl(win,100,"win")

such as...

MouseOverControl(win,100,"win","L")

Where win - window
100 - control ID
"win" is the name of the window i.e. win
"L" for control type - here a list box.

Any thoughts anyone?

Thanks,
Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Egil

October 21, 2016, 07:34:57 AM #5 Last Edit: October 21, 2016, 07:37:41 AM by Egil
Just a crazy thought...

Why not use an extra variable as a flag, and set its value to what you have decided to represent each specific control?
Such a system can easily be expanded to any number of different control types.


Egil

Support Amateur Radio  -  Have a ham  for dinner!

Andy

Egil,

Thanks for that thought, yes i think i will do that, e.g.

B for button, C for checkbox, L for listbox, S for static etc.

Good idea!

Thanks,
Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Egil

If you use an int or uint, you can even detect several "states" of the control.
Or you can use a char, where each bit represents a specific  control, and then do some bit-testing when the mouseover control detects it is over a control to determine what type of control it is.

The only limit  for how to do it, is your imagination ;D ;D ;D
Support Amateur Radio  -  Have a ham  for dinner!

Andy

Egil,

Yes another good point!

I am very proud over my mouse over controls include file, it allows hot tracking of the mouse and provides a visual aspect to a normal window, i.e. You can use it to make any control do something when the mouse is over it.

Think i will work on the next version of it, and hopefully release it soon.

Thanks for all you help, as always,

Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

fasecero

This can be a quick way to get the control name that's under the mouse


$INCLUDE "windowssdk.inc"

SUB ControlNameAtCursor(WINDOW w), string
string controlName = ""

POINT p
p.x = MOUSEX()
p.y = MOUSEY()
ScreenToClient(w.hwnd, p)

HWND handle = ChildWindowFromPoint(w.hwnd, p)
IF handle THEN GetClassName(handle, controlName, 255)

RETURN controlName
ENDSUB

Andy

Thanks Fasecero for that,

I tried what you suggested but it didn't work for me, the controlname string only came back with two messages:

Button, or EmergenceWhdClass, even when it was over different types of controls, so I decided to use my own manual labeling system for my MouseOverControls.inc file.

http://www.ionicwind.com/forums/index.php?topic=5943.msg43865#new

But thanks anyway for trying.
Andy.

Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

I've looked further into Fasecero's GetClassName suggestion.

It seems that it works for:

Statics,
Edit's
Listboxes and buttons.

However, checkboxes and radiobuttons are being detected as buttons as well. 
I wonder if there's a way to get more detailed information about a control, and would that be enough to correctly detect checkboxes and radiobuttons.

The EmergenceWhdClass appears when the mouse is not over any control.

Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

fasecero

Apparently they all share the same ("Button") predefined class name. I think you have to go a step further and return a fictitious class name  :)


SUB ControlNameAtCursor(WINDOW w), string
string controlName = ""

POINT p
p.x = MOUSEX()
p.y = MOUSEY()
ScreenToClient(w.hwnd, p)

HWND handle = ChildWindowFromPoint(w.hwnd, p)

IF handle THEN
GetClassName(handle, controlName, 255)

' Here we handle the different button types
IF UCASE$(controlName) = UCASE$("Button") THEN
DWORD dwStyle = GetWindowLong(handle, GWL_STYLE)

IF (dwStyle & BS_TYPEMASK) = BS_AUTOCHECKBOX THEN controlName = "CHECKBOX"
IF (dwStyle & BS_TYPEMASK) = BS_AUTORADIOBUTTON THEN controlName = "RADIOBUTTON"
ENDIF
ENDIF

RETURN controlName
ENDSUB

Andy

Fasecero,

That's great how you went a little deeper on the buttons, and by using the style you were able to determine the actual control type - great work!

I'm now wondering about the next problem, which is to get the actual name of the window when I create one with OPENWINDOW.

i.e. OPENWINDOW win2,100,100,390,470 .......

How to get the "win2" parameter.

I know (and have used) the windows handle, but that only returns a number specific to that instance of that window - not what I have defined it as i.e. win2.

So that's my next puzzle I have to work on.

Thanks,
Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

fasecero

If I understand you correctly, you want to get "win2" variable name as string. There is no built-in function that I'm aware of to convert a variable name to string. But you can assign a custom string to each WINDOW variable and later on get that string back whenever you need it.


OPENWINDOW win1, ...
string win1_str = "win1" : SetWindowLong(win1.hwnd, GWL_USERDATA, &win1_str) ' win1_str must not be a local variable

OPENWINDOW win2, ...
string win2_str = "win2" : SetWindowLong(win2.hwnd, GWL_USERDATA, &win2_str) ' win2_str must not be a local variable


We have to modify the function again to return those values


SUB ControlNameAtCursor(WINDOW w), string
string controlName = ""

POINT p
p.x = MOUSEX()
p.y = MOUSEY()
ScreenToClient(w.hwnd, p)

HWND handle = ChildWindowFromPoint(w.hwnd, p)

IF handle THEN
GetClassName(handle, controlName, 255)

' Here we handle the different button types
IF UCASE$(controlName) = UCASE$("Button") THEN
DWORD dwStyle = GetWindowLong(handle, GWL_STYLE)

IF (dwStyle & BS_TYPEMASK) = BS_AUTOCHECKBOX THEN controlName = "CHECKBOX"
IF (dwStyle & BS_TYPEMASK) = BS_AUTORADIOBUTTON THEN controlName = "RADIOBUTTON"
ENDIF

' Here we handle each window name
IF UCASE$(controlName) = UCASE$("EmergenceWhdClass") OR UCASE$(controlName) = UCASE$("EmergenceDlgClass") THEN
pointer prop = GetWindowLong(handle, GWL_USERDATA)
IF prop THEN controlName = *<string>prop
ENDIF
ENDIF

RETURN controlName
ENDSUB

Andy

Fasecero,

That's fantastic for me, what it means is that I can (and have) reduced down the number of parameters needed in my MouseOverControls include file.

Example:

Before, to register a control the format was like this - MouseOverControl (win,button_1,"win","B")

Now it is (when I release the new version) like this - MouseOverControl (win,button_1)

Other commands have also benefited:

Before - TrackWindow(win,"win") - now it is TrackWindow(win) etc...

Thanks, I will give you a mention in the new help file if you'd like.

Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

fasecero

I'm glad it has helped you. Over the years this forum has helped me immensely (and still it does every time I have to write something) and hopefully I can contribute a bit, so just mention the forum if you want to. Good luck with your project!

Andy

Thank Fasecero,

I always try when I can to promote IWB and the forum.

Thanks again for your help.

Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

sam.cogswell

I have found that when creating a window, a border is 3 pixels on the left, right, and bottom.  The top includes this PLUS 27 for the title height.  This means that the workable area of the window is 6 pixels shorter in width because of the right and left borders.   I discovered this while trying to place a button on the right edge of a window by subtracting it's width from the window width to keep it properly positioned when resizing.
I haven't measured this for other controls, but it may be that the size you set includes this border as well just as in a window.

Andy

Sam,

That's interesting.

What I have found is that with a new command I'm now including in my MouseOverControls include file, that the left, right, and bottom border of a window is actually detected as part of the "caption" area of the window.

I did start on a formula, but it seems that the constant does actually change depending on size of fonts.

It also seems that these fonts are grouped, i.e. the constant changes within certain ranges of fonts.

Thanks,
Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

ckoehn

October 30, 2016, 04:56:36 PM #20 Last Edit: October 31, 2016, 12:22:52 PM by ckoehn
You can get the borders and title height with something like this..

/* mCaptionHeight is the default size of the NC area at
// the top of the window. If the window has a caption,
// the size is calculated as the sum of:
//      SM_CYFRAME        - The thickness of the sizing border
//                          around a resizable window
//      SM_CXPADDEDBORDER - The amount of border padding
//                          for captioned windows
//      SM_CYCAPTION      - The height of the caption area
//
// If the window does not have a caption, mCaptionHeight will be equal to
// `GetSystemMetrics(SM_CYFRAME)`*/
int height = (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION) +GetSystemMetrics(SM_CXPADDEDBORDER))


You can get the window border out of this as well as the title height.

Haven't exactly tried this code but a long time ago it was something like that.

You will need $INCLUDE "windowssdk.inc" at the top.
Later,
Clint

Egil

QuoteYou can get the window border out of this as well as the title height.

Haven't exactly tried this code but a long time ago it was something like that.

You better read this before trying this with Windows 10:
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/a910e656-5829-4e5e-8adb-54cfac088a9f/problem-with-system-metrics-smcxsizeframe-smcxpaddedborder-in-windows-10-preview-build-10041?forum=vcgeneral


Egil
Support Amateur Radio  -  Have a ham  for dinner!

Andy

November 02, 2016, 06:26:22 AM #22 Last Edit: November 02, 2016, 06:27:55 AM by Andy
Egil,

That's interesting reading, it's a pity GetSystemMetrics can no longer be relied upon for these regions.

I've noticed many little differences in the Windows versions (XP onwards), I first found these in the registry.

In XP a registry setting could be "do this", and in Vista it was "do that".

So in some of my software I had to detect what OS version a user was using, and then use the correct registry setting.

It's a pity MS just don't leave some of these legacy commands / functions in (or at least make sure they still work).

Andy.


Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Egil

I found out the hard way, when I started on my map project. The functions that called GetSystemMetrics worked fine while using WinXP but not with Win7.
Wonder how many other similar functions we no longer are allowed to use?
Support Amateur Radio  -  Have a ham  for dinner!