Silverfrost Forums

Welcome to our forums

Address of data being modified by a control

14 Oct 2018 4:28 #22669

What way is best way to associate an address of data (specifically, character data, but extensible to others) with a control?

I ask this because I have different handlers doing the exact same task, but pointing to different data items. Yes, I could have separate callbacks, then invoke a common data handler using the specific data item in the call, but this kind of defeats the purpose of making the handler totally independent of the location of the data item itself.

I have two handlers to deal with similar data types. I want the user to enter numeric data into a single control as numeric fields separated by spaces. I want to attach a callback to see if all the data in the field is either a space or a digit. But only if I can access the character data field actually being modified. Luckily for me, the handler would only deal with character strings of identical length (i.e. if the control is 32 characters, it will always be 32 characters, regardless of where it might appear).

I can envision a very complex set of winio@() setup code to create a control and save the control window and LOC() of the data as the window is being built, but this is a complex solution to what might be a simple problem.

I've been through the documentation, searching for potential solutions, but don't see anything that looks good (except some of the vc() routines but they require a control ID number along with the window handle). If none exists, then so be it.

15 Oct 2018 6:14 #22672

The first thing that comes to mind is to use the HWND (from %lc) of the control together with the Windows API functions SetWindowLong and GetWindowLong (with GWL_USERDATA). For 64 bits these become SetWindowLongPtr and GetWindowLongPtr with GWLP_USERDATA.

Let me know which type of control you wish to use so that I can check that ClearWin+ does not use this data point for its own purposes.

If this is of general interest then it may be possible to make this approach more user friendly for ClearWin+ users.

15 Oct 2018 12:20 #22677

You use SetWindowLong in your program and this is translated to SetWindowLongA via INCLUDE <window.ins> or its equivalent.

Basically A is for ASCII characters and W is for 'Wide' which means UNICODE.

15 Oct 2018 3:49 #22678

Paul and Jon,

Thanks for the response!

Using SetWindowLong can certainly be used to attach a pointer to a control. I had seen something similar with the vc*() functions. I should have realized that there was a similar capability using MSWIN!

I intend to use this with %rs, %rd, %rf, %ls, and %lv controls. I have a dialog that allows the user to select an item from a list that is dynamically created from both %ls and %lv controls, then populate individual controls from that data in the list. It is this population after selection that will use the pointer to the data.

As an alternative, perhaps I could attach the address of a TYPE to the window itself, but only if %hw immediately returns the handle to the window/dialog being created.

I never have two instances of this window/dialog active at any time, so there are likely some other alternatives that can also be used with SetWindowLong and GETWINDOWLONG.

You both have given me some things to consider. I am interested to see if there are restrictions, Paul. Then, I'll work around them!

16 Oct 2018 6:19 #22685

I have given this some thought and it would be safer if ClearWin+ provided its own equivalent of GWL_USERDATA. If you can wait a week or two then I will see what can be done.

16 Oct 2018 1:23 #22688

Paul, not a problem for me at all. Thanks for the consideration.

31 Oct 2018 3:13 #22719

I have added a 'user data' feature to ClearWin+ on a trial basis.

Here are two links for downloading the trial DLLs and INCLUDE/MOD files. The latter files go in the FTN95\INCLUDE folder.

Please note that these DLLs don't contain any 'fixes' unless these have been notified elsewhere on the forum.

Two following two posts contain sample programs that illustrate the concept.

https://www.dropbox.com/s/1hlmdk40g82710t/clearwin64.zip?dl=0

https://www.dropbox.com/s/l4dato3eulqd3qr/CLEARWIN.zip?dl=0

31 Oct 2018 3:14 #22720
WINAPP
program main
integer iw,winio@
character*1024 buffer
integer data1
integer,external::cb
data1 = 0
buffer = ' '
iw = winio@('%ca[User data]&')
iw = winio@('%30.10^re&',buffer,cb)
iw = winio@('%ud&', loc(data1))
iw = winio@('%ff%nl%cn&')
iw = winio@('%10rd',data1)
end

integer function cb()
use clrwin
integer(7) addr
addr = clearwin_info@('USER_DATA')
core4(addr) = core4(addr)+1
cb = 1
end function
31 Oct 2018 3:15 #22721
WINAPP
program main
use clrwin
character*1024 buffer
integer iw,data1,ictrl
integer,external::cb
integer(7) hwnd
common hwnd
data1 = 0
buffer = ' '
iw = winio@('%ca[User data]&')
iw = winio@('%30.10^re&',buffer,cb)
iw = winio@('%lc&', hwnd)
iw = winio@('%ff%nl%cn&')
iw = winio@('%10rd&',data1)
iw = winio@('%lw',ictrl)
call set_user_data@(hwnd, loc(data1))
end

integer function cb()
use clrwin
integer(7) addr,hwnd
common hwnd
addr = get_user_data@(hwnd)
core4(addr) = core4(addr)+1
cb = 1
end function
31 Oct 2018 4:49 #22723

Nice, Paul! Thanks for the samples.

If I may put this in verbiage:

%ud assigns a user data field to the previous control, and the contents of the user data field is retrievable via clearwin_info@.

set_user_data@ and get_user_data@ allow the user to set and retrieve a user data field from a window.

Did I get it correct?

Thanks for the time and effort on this. It will be very useful to me (for sure) and others (I believe).

31 Oct 2018 5:21 #22724

Yes. %ud works like %lc in this respect (using the previous control).

In this context, clearwin_info@ must only be called from a callback function for the corresponding control.

The two samples illustrate alternative approaches. Either approach can be used or the two can be mixed.

31 Oct 2018 8:16 #22726

Thanks for verifying, Paul. I'll give it a go!

13 Dec 2018 3:16 #22998

Paul, I've had a chance to play with these new capabilities. I have one question for you.

Can the same function be used to set the User Data for a window (or a dialog)? I can see that there may be some problem associated with this if ClearWin+ uses the User Data for the window or dialog for it's own purposes.

If the answer is yes it can be used, then at what point is the handle to the window (or dialog) created? For example: If I were to use the %hw, does this update the handle variable only AFTER the window is created, thus requiring %lw be used?

Bill

13 Dec 2018 3:37 #22999

Bill

I would not recommend using GWL_USERDATA and SetWindowLongPtr in ClearWin+ programs. This data point may already be used or is reserved for future developments.

Something like %ud could be added for main windows (as at the moment for controls) if this was of general interest.

13 Dec 2018 4:23 #23000

Thanks for taking a look, Paul. I'll pursue other options.

14 Dec 2018 9:10 #23005

Paul, I am attempting to use this feature with a %ls, but the value returned is always zero.

Are there some controls for which no assignment of User_Data can be made?

15 Dec 2018 8:00 #23006

No. It should work for any control.

Can you post some code that illustrates the failure?

15 Dec 2018 2:50 #23012

I used your code, and added the %ls construct. The intent was do decrement 'data2' when either (a) data1 was modified, or (b) when a list element was selected.

The address returned was zero (error thrown) when the list was selected.

!    PROGRAM Simple
 WINAPP 
 program main 
 integer iw,winio@ 
 character*1024 buffer
 character*10 list_elements(5)
 integer list_sel 
 integer data1,data2
 integer,external::cb ,cb2
 data1 = 0
 data2 = 0 
 buffer = ' '
 list_elements = 'abcd defg'
 list_sel = 1 
 iw = winio@('%ca[User data]&') 
 iw = winio@('%30.10^re%ff&',buffer,cb) 
 iw = winio@('%ud&', loc(data1))
 iw = winio@('%ff%nl%cn&') 
 iw = winio@('%^10rd&',data1,cb2)
 iw = winio@('%ud&',loc(data2))
 iw = winio@('%10rd&',data2)
 iw = winio@('%ff%nl%^10.10ls&',list_elements,5,list_sel,cb2)
 iw = winio@('%ud&',loc(data2)) 
 iw = winio@(' ')
 print *,data2 
 end 
 
 integer function cb() 
 use clrwin 
 integer(7) addr 
 addr = clearwin_info@('USER_DATA') 
 core4(addr) = core4(addr)+1 
 cb = 1 
 end function

 integer function cb2() 
 use clrwin 
 integer(7) addr 
 addr = clearwin_info@('USER_DATA') 
 core4(addr) = core4(addr)-1 
 cb2 = 1 
 end function
15 Dec 2018 5:33 #23015

Yes. This fails and I have fixed it in ClearWin+. I will aim to send new DLLs early next week.

I think that you probably don't need the line..

iw = winio@('%ud&',loc(data2))

at about line 20.

15 Dec 2018 9:48 #23017

The intent was to see, if it worked, that the callback had the correct pointer to the data for that rd field. Obviously, didn't need it, but if it had worked, I wanted to know!

Thanks for all the work. As I go through my code, I'll be adding in the %ud calls to other controls. The way I'm structuring the recode, I retain the existing code to populate various variables, and when the callback is successful with 'USER_DATA', I'll begin larger changes. In this case, the %ls was my first set to begin!

Again, many thanks! Bill

Please login to reply.