October 29, 2025, 01:09:28 PM

News:

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


Diable a control

Started by Andy, August 22, 2014, 04:06:38 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

Hi,

I have several checkboxes on a screen, each checkbox refers to a test that the user either wants (ticked)
or does not want (unticked).

The user then presses a button which starts the "tests" and for each checkbox there is a corresponding value displayed next to it.

The question is this:

Whilst these tests are running how do I stop the user from ticking or unticking any of the checkboxes?

Enablecontrol works but it greys out the control - if the checkbox is ticked I don't want it greyed out.

So how can I stop a user from ticking / unticking a checkbox, and how do I enable it again after a "test" has finished?

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

LarryMc

give me a bit to figure which is the best way to accomplish it.
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

Turns out it wasn't as easy as I thought it was going to be.

I thought at first all I had to do was subclass the @checkbox control and use the regular API to draw the checkbox and the text.
Well it turns out that the MS API flags to set up an ownerdrawn checkbox are incompatible and it won't work.
So scratch that.

So, I went to a captionless, transparent child window to cover the checkboxes when the test is running so the boxes couldn't be checked..
One little problem; the API won't let you make a CHILD window transparent.

So, I created a captionless, transparent window that wasn't a child.
One little problem; that creates two windows in the task bar.

So, I created a captionless, transparent, @toolwindow window that wasn't a child.
Had to add code to hide the window when it was created
Had to adjust the windows screen coordinates to  the main window's client coordinates so it covers the desired checkboxes
Had to add code so that if the user moves the main window the toolwindow will go with it.

In the following code I made the toolwindow red so you can see what is happening.
This line
SetLayeredWindowAttributes(hw.hwnd, 0, 155, LWA_ALPHA)
is what controls the transparency.  After you run it and check out how it works change the 155 to 0 and you won't be able to see the toolwindow at all.
When you are in test mode the hw is shown and covers the boxes, preventing them from being clicked.
When the test is over then everything works normal
And since you never use the enable command the checkboxes don't change color.


$INCLUDE "WINDOWSSDK.inc"

window w,hw
uint x,y
openwindow w,0,0,520,300,@CAPTION|@SYSMENU,0,"Check Disable Demo",&mainwindow
hw_pos()
OPENWINDOW hw, x+56,y+100,70,80,@toolwindow|@nocaption|@hidden|@topmost, 0, "",&winproc
SETWINDOWCOLOR hw,rgb(255,0,0)
MODIFYEXSTYLE hw, WS_EX_LAYERED, 0
SetLayeredWindowAttributes(hw.hwnd, 0, 155, LWA_ALPHA)

CONTROL w,@checkbox,"Test 1",56,100,70,20,0, 100
CONTROL w,@checkbox,"Test 2",56,120,70,20,0, 101
CONTROL w,@checkbox,"Test 3",56,140,70,20,0, 102
CONTROL w,@checkbox,"Test 4",56,160,70,20,0, 103



CONTROL w,@BUTTON,"End Test",10,40,120,20,0,1
SETFONT w, "tahoma", 8, 700,  0,1
CONTROL w,@BUTTON,"Start Test",10,10,120,20,0,2
SETFONT w, "tahoma", 8, 700,  0,2
waituntil w=0
end

sub mainwindow (),int
select @CLASS
case @IDCREATE
CENTERWINDOW #<WINDOW>@HITWINDOW
case wm_moving
hw_pos()
MoveWindow(hw.hwnd,x+56,y+100,70,80,0)
case @IDCLOSEWINDOW
closewindow hw
closewindow w
case @IDCONTROL
SELECT @CONTROLID
case 1
showwindow hw,0
case 2
showwindow hw,1
endselect
endselect
return 0
ENDSUB

sub hw_pos()
uint l,t,w1,h
point pt
GETCLIENTSIZE w, l, t, w1, h
ClientToScreen(w.hwnd,pt)
x=pt.x
y=pt.y
return
endsub

SUB winproc(),int
IF @MESSAGE = @IDCLOSEWINDOW THEN closewindow hw
RETURN 0
ENDSUB


LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

GWS

Good grief Larry - you're persistent ..  ;D

Another suggestion - When the 'Run Tests' button is clicked, set a flag 'Locked = True'.

Then in the CASE @IDCONTROL .. IF @CONTROLID = Test1 etc section, place an IF (Locked = False) check - in which case procede as at present, or IF (Locked = True), ignore any changes to the checkboxes until 'Locked' becomes False again. :)

Would that do the trick?

Best wishes, :)

Graham
Tomorrow may be too late ..

LarryMc

Graham
When the main window handler receives the message that says the checkbox has been clicked (toggled) it is already too late.
The check mark has already been changed by the OS. That's why my first attempt was to subclass and catch it before the message was sent.

But, you did give me an ideal for another possible way to do it.

Be back in a while  ;)
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

I had it right in the very beginning when I said subclass the checkboxes.
Where I went wrong is thinking that I needed to draw the checkbox.

In reality, all I had to do in the subclass is trap the down button and the up button messages and discard them when the global variable(freeze) is set and when freeze is not set just pass the message thru to the standard handler.  Real Simple.


$INCLUDE "WINDOWSSDK.inc"


window w
int freeze=0
string LPFNPROP
LPFNPROP= "Z8TD96"
openwindow w,0,0,520,300,@CAPTION|@SYSMENU,0,"Check Disable Demo",&mainwindow 
CONTROL w,@checkbox,"Test 1",56,100,70,20,0, 100
CONTROL w,@checkbox,"Test 2",56,120,70,20,0, 101
CONTROL w,@checkbox,"Test 3",56,140,70,20,0, 102
CONTROL w,@checkbox,"Test 4",56,160,70,20,0, 103

CONTROL w,@BUTTON,"End Test",10,40,120,20,0,1
SETFONT w, "tahoma", 8, 700,  0,1
CONTROL w,@BUTTON,"Start Test",10,10,120,20,0,2
SETFONT w, "tahoma", 8, 700,  0,2
SetProp(getcontrolhandle(w,100), LPFNPROP, SetWindowLong(getcontrolhandle(w,100), GWL_WNDPROC, &MyCheckProc))
SetProp(getcontrolhandle(w,101), LPFNPROP, SetWindowLong(getcontrolhandle(w,101), GWL_WNDPROC, &MyCheckProc))
SetProp(getcontrolhandle(w,102), LPFNPROP, SetWindowLong(getcontrolhandle(w,102), GWL_WNDPROC, &MyCheckProc))
SetProp(getcontrolhandle(w,103), LPFNPROP, SetWindowLong(getcontrolhandle(w,103), GWL_WNDPROC, &MyCheckProc))

waituntil w=0
end

sub mainwindow (),int
select @CLASS
case @IDCREATE
CENTERWINDOW #<WINDOW>@HITWINDOW
case @IDCLOSEWINDOW
closewindow w
case @IDCONTROL
SELECT @CONTROLID
case 1
freeze=0
case 2
freeze=1
endselect
endselect
return 0
ENDSUB


sub MyCheckProc(int hwnd,UINT uMsg,int wParam,int lParam),int
int proc = GetProp(hwnd, LPFNPROP)
select uMsg
case WM_DESTROY
SetWindowLong(hwnd, GWL_WNDPROC, proc)
RemoveProp(hwnd, LPFNPROP)
case WM_LBUTTONDOWN
if freeze=1 then return 0
case WM_LBUTTONUP
if freeze=1 then return 0
endselect
return CallWindowProc(proc, hwnd, uMsg,wParam,lParam)
endsub

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

GWS

OK .. none of this hi-tech subclassing stuff ..  ;D

Here's a version that just uses basic logic tests - nothing fancy ..


' Checkbox Test

def w:window
def wstyle:int
def state1,state2,locked,run:int

wstyle = @minbox

autodefine "off"

' open a window ..
openwindow w,-600,0,600,400,wstyle,0,"Not Creative Basic",&main
setwindowcolor w,rgb(0,60,190)
centerwindow w

control w,@Button,"Exit",(600-70)/2,310,70,30,0,100

'Create checkbox buttons
control w,@CHECKBOX,"Selection 1",170,100,180,30,0,1
control w,@CHECKBOX,"Selection 2",170,140,180,30,0,2

control w,@Button,"Test",(600-70)/2,210,70,30,0,4

control w,@STATIC,"",380,100,70,30,@cteditcenter|0x200,10
control w,@STATIC,"",380,140,70,30,@cteditcenter|0x200,11
control w,@STATIC,"",360,209,70,30,@cteditcenter|0x200,12
setcontrolcolor w,12,0,rgb(180,180,250)

locked = 0 :' Test not yet started

run = 1

WAITUNTIL run = 0
CLOSEWINDOW w
END

SUB main
select @class
case @idclosewindow
run = 0
case @idcontrol
select @controlID
case 100
run = 0

case 1 :' Checkbox 1 selected
if(locked = 0)
if GETSTATE (w,1) = 1
setcontroltext w,10,"Set"
else
setcontroltext w,10,""
endif
else
select 1
case state1 = 1
setstate w,1,1
case state1 = 0
setstate w,1,0
endselect
endif

case 2 :' Checkbox 2 selected
if(locked = 0)
if GETSTATE (w,2) = 1
setcontroltext w,11,"Set"
else
setcontroltext w,11,""
endif
else
select 1
case state2 = 1
setstate w,2,1
case state2 = 0
setstate w,2,0
endselect

endif

case 4 :' Test started
if (locked = 0)
locked = 1
setcontroltext w,12,"Locked"
setcontrolcolor w,12,0,rgb(250,180,180)
state1 = GETSTATE (w,1)
state2 = GETSTATE (w,2)
else
locked = 0
setcontroltext w,12,""
setcontrolcolor w,12,0,rgb(180,180,250)
endif

endselect
endselect
RETURN
ENDSUB



Yeuk, I can't believe I've done this in IWB.  Venture out of simple Creative and the problems start - had to re-write the Window statement and all the control statements.  Even then I get an incomprehensible Warning compilation message about IWBWNDPROC whatever that is. ::)

Never mind it works, so that's the main thing.

Best wishes, :)

Graham

Tomorrow may be too late ..

LarryMc

QuoteYeuk, I can't believe I've done this in IWB.  Venture out of simple Creative and the problems start - had to re-write the Window statement and all the control statements.  Even then I get an incomprehensible Warning compilation message about IWBWNDPROC whatever that is.
;D ;D
Now you know what I have to go thru to convert from IWB and CB. ::) ;D
As for the warnings you got.
You need to change two lines to take care of that.
change thisSUB main to thisSUB main(),int
and thisreturnto thisreturn 0

But the serious question is does your solution really work?
I have knowledge about the internals of Andy's program that you don't have for copyright reasons.
So what I did was modify your solution's code to add the timer that is used to check the state of the checkboxes very often when things are "locked".

I wanted to see if the shuffling of things internally by windows would allow the change of state to be sensed before your code has a chance to switch it back.
As best I can test your solution works without causing any other problems with what Andy is doing.  So congrats!!  Just goes to show how good of a programmer you are and that no one should sell us old farts short. ;D ;D ;D

So, after adjusting your code to be structure like mine our solutions are not that much different in size.

The only visual difference I see is that with your solution you see a flicker when things are froze and the user clicks a checkbox.  The flicker is because the checkbox is actually changing state and then changing back.  No big deal.

With my solution there is no flicker because the checkbox isn't allowed to change state at all when frozen.

Regardless of the slight flicker, good work ole friend.
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

GWS

Woohoo ! .. no more warnings ..  ;D  A clear compile.
Thanks Larry - I'll try to remember that.

And thanks to Andy for a nice brain teaser.

I noticed the slight flicker - not much more than the normal blink as you change the selection.
I even tried taking the window off-screen while the change was reversed - but there was no improvement.
So on the basis that Larry's hi-tech method inherently has no flicker, I guess his method wins ..  ;D ;D

Best wishes, :)

Graham
Tomorrow may be too late ..

Andy

Larry and Graham,

Thanks guys for looking at the checkbox problem.

Only sorry I didn't really have time to say thanks earlier!

I'm adding in the solution as we speak, so I can get a full test done tomorrow and let you guys know how I
went on with it.

Once again, a BIG THANK YOU!
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.