April 30, 2024, 07:47:26 PM

News:

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


New control

Started by LarryMc, November 05, 2007, 03:20:15 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

LarryMc

November 05, 2007, 03:20:15 PM Last Edit: November 06, 2007, 12:13:28 PM by Larry McCaughn
Paul,
Is adding a new control that is not based on any other control hard to do.

Especially considering I know nothing about C.

I looked in EBasic source for addcontrol etc.

Don't have a clue about the dlgtemplate thingy or class.

With my limited skill set would you just suggest I find something else to get involved in?

For the sake of arguement let's say I wanted a control that was a round gage that you'd pass range, units, high and low alarm limits name and current pointer location to and it in turn would send low and high alarm messages when the alarm limits are exceeded.

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

Haim

I would like to join in this request.
I have been experimenting with this for a while (in Aurora) and even got some results but an explanation/tutorial from the master would be very appreciated.
Haim

Ionic Wind Support Team

Saw the post, still thinking about the best way to answer ;)

I guess it depends on what you want the control for.  If it is just for your own programs then just create yourself a window, without a caption, and go for it.  If you want to share the control with other languages then it gets a bit more complicated, you have to create a DLL, register a system wide control class, handle certain messages, etc. 

Paul.
Ionic Wind Support Team

LarryMc

November 07, 2007, 01:20:54 PM #3 Last Edit: November 07, 2007, 01:24:40 PM by Larry McCaughn
I had thought about using a window(since I discovered how to make no rectangle windows).
Then there's the problem of fixin the position of multiple windows on top of the other and not running into focus and positioning issues.
The "window "docking' example takes care of the positioning issue, I think.

Then comes the non-standard messages I would need to send to the main window handler.
I think I can use sendmessage for that but haven't looked into that.

Also, my new control would have to do its "thing" based on a timer in its own handler.
That's were the sendmessage would be created and sent to the main window.

On top of all that there's the fact that I would want to create the new control as a oop class.

That raises another issue of how to automatically trigger the closing of my "control" windows when the main window is closed; without the class user have to hardcode the closing of each of my controls individually.
Have no idea about that?

Does that sound anywhere near close and doable?

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

LarryMc

In the old forum CD I found a custom control for a "DrawPad" class.

Don't know if I'm smart enough to sort it out.

Would I need my own controlex routine to handle the different look?

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

Ionic Wind Support Team

ControlEx creates any registered control class.  It is a generic function.
Ionic Wind Support Team

LarryMc

Quote from: Paul Turley on November 06, 2007, 09:45:16 PM
... have to create a DLL, register a system wide control class, handle certain messages, etc. 

I can handle making a dll ( I could share it with other EB users as a lib, couldn't I?)

In the dll/lib I'd have to have an "init" routine to be called at the beginning of the users program in order to "register" a system wide control class before the control was actually used; right?  It's a one time deal?

Larry

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

LarryMc

Found where you create windows in the source code.
I seen where you use the global variable  "main_atom" for registering a globalclass.
I seen that I can create my own "atom" so-to-speak to register my class which will keep the user from having to call an init routine.

I'm learning a little.
I've got the skeleton of my class built and I'm working on the drawing aspect of it now.

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

LarryMc

December 07, 2007, 12:24:38 PM #8 Last Edit: December 07, 2007, 12:39:58 PM by Larry McCaughn
Having a problem with drawing my control.
Here's the code that paints my test control: PAINTSTRUCT ps
WINRECT     rc

     case WM_PAINT
         _BeginPaint(hWnd, ps)
         _GetClientRect(hWnd, rc)
         hdc     = _CreateCompatibleDC(ps.hdc)
         hBitmap = _SelectObject(hdc, _CreateCompatibleBitmap(ps.hdc, rc.right, rc.bottom))

'set color of panel(background)
brush = _CreateSolidBrush(#pgagep.nPanelColor)
         _FillRect(hdc, rc, (brush))
_DeleteObject(brush)

'draw outer gage ring
brush = _CreateSolidBrush(RGB(100, 100, 100))
oldBrush = _SelectObject(hdc,brush)
SetArcDirection(hdc, 2)
Arc(hdc, rc.left, rc.top, rc.right, rc.bottom, 0, 0, 0, 0)
Arc(hdc, rc.left+8, rc.top+8, rc.right-8, rc.bottom-8, 0, 0, 0, 0)
pixelcolor = GetPixelA(hdc,rc.left+3,(rc.bottom-rc.top)/2+rc.top)
ExtFloodFill(hdc,rc.left+3,(rc.bottom-rc.top)/2+rc.top,pixelcolor,1)
_DeleteObject(oldbrush)

'color center of gage
brush = _CreateSolidBrush(RGB(130, 130, 130))
oldBrush = _SelectObject(hdc,brush)
pixelcolor = GetPixelA(hdc,rc.left+100,rc.top+100)
ExtFloodFill(hdc,rc.left+100,rc.top+100,pixelcolor,1)
_DeleteObject(oldbrush)

        _SetBkMode(hdc, TRANSPARENT)
        DrawText(hdc, szText, wsprintf(szText, TEXT("%u%%"), INT(dPercent * 100)), &rc, DT_CENTER | DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER)

'         _BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdc, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY)
'        _StretchBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, (ps.rcPaint.right - ps.rcPaint.left)*.5, (ps.rcPaint.bottom - ps.rcPaint.top)*.5, hdc, ps.rcPaint.left, ps.rcPaint.top, (ps.rcPaint.right - ps.rcPaint.left), (ps.rcPaint.bottom - ps.rcPaint.top), SRCCOPY)

         _DeleteObject(_SelectObject(hdc, hBitmap))
         _DeleteDC(hdc)
         _EndPaint(hWnd, ps)
         return 0

Toward the bottom of the code are 2 lines that are remarked out: _BitBlt and _StretchBlt
If I compile with _BitBlt the routine works as I expect it to. (see P1.jpg)
If I minimize the window and then bring it back it still looks the same.

If I compile with _StretchBlt the routine works as I expect it to. It displays at 1/2 height and width (see P2.jpg)

However, if I minimize the window and then bring it back I get bleed-through (no redraw of the original part of the window that is not covered by the reduced image.(see P3.jpg)

I have no idea how to fix it or even if it is fixable or not.

Help

Edit: What I'm wanting to do is draw my control at one fixed size then scale it to fit the size requested in the calling add-control function.

What I think I need is:
1. one bitmap that is sized to height/width passed in by the add-control function.
2. another bitmap that is a fixed size that I do all my drawing to.
3. and then stretchblt the 2nd one into the first one
but I don't know how to do it.

Larry


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

Ionic Wind Support Team

If you are using a standard Ebasic window as the base for your control then the BeginPaint function is not necessary and will invalidate the update region for the window.

When @IDPAINT (WM_PAINT) is sent to your handler the DC has already been set up for you.

Paul.
Ionic Wind Support Team

LarryMc

December 07, 2007, 03:04:39 PM #10 Last Edit: December 07, 2007, 03:06:14 PM by Larry McCaughn
I think I'm doing it from scratch.

if gage_atom=0
  WNDCLASSEX wc
   wc.cbSize        = len(WNDCLASSEX)
   wc.style         = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW
   wc.lpfnWndProc   = &Gage1Proc_LM
   wc.cbClsExtra    = 0
   wc.cbWndExtra    = 0
   wc.hInstance     = _hinstance   
   wc.hIcon         = NULL
   wc.hCursor      = LoadCursor(NULL, IDC_ARROW)
   wc.hbrBackground = NULL
   wc.lpszMenuName  = NULL
   wc.lpszClassName = "LM_Gage1_Class"
   wc.hIconSm       = NULL
  gage_atom=_RegisterClassEx(wc)
endif

sub AddGage(win as WINDOW,l as INT,t as INT,d as INT,id as UINT)
   RegisterGage1Class()
   CONTROLEX win,"LM_Gage1_Class","",l,t,d,d,0,0,id
return
endsub

sub Gage1Proc_LM(hWnd:UINT, uMsg:UINT, wParam:UINT, lParam:UINT),UINT

endsub

Like I said, it works fine except I don't know how to implement 2 bitmaps in that section of code.
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Well you are doing it yourself,   

Don't forget you need to handle background updates as well.  WM_PAINT is for the foreground, WM_ERASEBKGRND is for drawing the areas that the control doesn't occupy.   Since your class doesn't have a background brush then you'll need to do it.  Or load a stock brush for  wc.hbrBackground in your WNDCLASSEX structure.

....Which is why you see the undrawn areas when minimized/restored.

Paul.

Ionic Wind Support Team

LarryMc

Quote from: Paul Turley on December 07, 2007, 03:21:58 PM
...  Or load a stock brush for  wc.hbrBackground in your WNDCLASSEX structure.

Made no difference

Here's what it appears I'm trying to get around:
This bit of code creates a bitmap with user dims (from myadd-control command) say 0,0,150,150
         _BeginPaint(hWnd, ps)
         _GetClientRect(hWnd, rc)
         hdc     = _CreateCompatibleDC(ps.hdc)
         hBitmap = _SelectObject(hdc, _CreateCompatibleBitmap(ps.hdc, rc.right, rc.bottom))

If I use the stretchblt command I can scale the image (say by a 4th) but all I'm doing is is shrinking the image downin size but but the ps. DC has the original area so I'm only writing out to 1/4 of the screen and that's why I get the "bleed-through".

I see the solution as I need 2 bitmaps; a fixed size one to do all my writing to; and the variable sized one to scale the fixed size one into. 

I just don't know how to do it yet.
Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Fill the background in response to  WM_ERASEBKGRND like I suggested

Paul

Ionic Wind Support Team

LarryMc

I can do that but it won't solve my ultimate problem.

If I write over the area that isn't being rewrote because I shrunk the image then what will happen to a 2nd control that is located in that area that isn't being refresh with the 1st control.

My gage control is going to be a round indicator, with a round scale, with tic marks along that round scale. The range of the scale and units is set by the user. 
Instead of having to do all the internal drawing with scale factors applied to sines and cosines I want to do all the internal calculations and drawing/text alignment and scaling with one fixed size rectangle which contains my gage (lets say 200X200 pixels) and one font size, etc.

Then, using stretchblt to to enlarge/reduce my internal bitmap to the bitmap that will be outputed to the screen at whatever size the user wanted.

When I can figure out how to implement 2 bitmaps inside the WM_paint routine ALL my problems will be resolved.

The "problem" I have now with the "bleed-thru" is because I'm not sending a big enough picture out to the screen to fill the area that was initialized into the ps structure.  I say that because when I send an image out that is the same size as the user's requested size then everything works fine. So that "problem" is just a normal side effect of doing what I did.  And that approach won't get me to where I want to go so the WM_ERASEBKGRND issue isn't relative.

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

Ionic Wind Support Team

OK so don't listen  ::)

I've built more custom controls then you can shake a stick at.   When you are handling the updates to your window you have to handle both the background and foreground.  Unless the foreground covers the entire area.  The WM_ERASEBKGRND message is sent by windows first, using the invalidated update region.  Your handler is supposed to fill the entire client area with a brush or solid color at this point, if you don't then you will get the effect you are experiencing.

Then Windows sends the WM_PAINT message with the invalidated area for the foreground, in which case your windows is supposed to draw the foreground elements.  Doesn't matter whether you use BitBlt or StretchBlt, that isn't the issue here.

You don't need two bitmaps for what you want to do.  But hey, if you want to go to all the trouble don't let me stop you...you will need to create two separate DC's, two bitmaps, etc....just to mimick the same effect that Windows already is trying to do by sending you the WM_ERASEBKGRND.

To each their own.

Paul.
Ionic Wind Support Team

LarryMc

December 07, 2007, 06:30:03 PM #16 Last Edit: December 07, 2007, 08:12:29 PM by Larry McCaughn
Quote from: Paul Turley on December 07, 2007, 06:19:09 PM
OK so don't listen  ::).....To each their own.

I'm sure that you are 100% correct.  I have stated numerous times before that I know absolutely nothing about C type coding.
I've gotten as far as I have with this effort via hours of looking at the SDK documentation that I downloaded and searching the internet and with an IBASIC progressbar program I found.

I promise that I won't furthur flaunt my ignorance by asking any more questions concerning MY difficulties in understanding.

I handled the WM_ERASEBKGRND and it took care of the "bleed thru".

However, it in no way got me closer to what I really wanted to do.

What I need to do is fool the wm_paint routine initially, when beginpaint is called, into thinking the client area is bigger than what it is.
While it is fooled do all my drawing then when I do the bitblt or stretchblt un-fool it and use the actual coordinates.

Stretchblt now simply puts a smaller version of the image in the client area.
I want to put a full size image in the client area but I wanted to do my drawing on a bigger version of the final image that is a predefined fixed size.  It makes % of small pixel increments and fillrect based upon pixel location work better.

I don't know how to accomplish that on my own and I refuse to ask any other questions on this subject, therefore,

the whole matter has died a natural death.

Thanks for responding.

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

Ionic Wind Support Team

Larry,
You don't need to "fool" WM_PAINT.   Create your bitmap as big as you want, it has nothing to do with the client size.  You can then freely StretchBlt it into the device context.

hdc = _CreateCompatibleDC(NULL)

Will give you a device context without confines, select the oversized bitmap into it and draw to your hearts content.  Then StretchBlt it into the paint DC. 

Emergence's own window class uses this method for autodrawn windows.  The internal bitmap is the same size as your screen, the client size doesn't affect the bitmap.  You've got the source code, feel free to use it.

This isn't "C" type coding, it is Windows GDI programming.  It isn't intuituve, and not for the feint of heat, it is the Microsoft way of doing things.  It can be a real pain in the A** to do at times, but there are set guidelines on how to accomplish your goals.

I wanted you to listen, and start with WM_ERASEBKGRND, because you need to take GDI programming one step at a time.  I don't have your source code, just the bits and peices you posted here.  I don't even know if you are handling other messages properly.  So my recommendations were meant to get you pointed in the right direction.  And to solve your immeidate problem.

Setting a background brush in your class should have worked, the fact that it didn't means you are returning from Gage1Proc_LM improperly somewhere.  Which was the next step in the progression of what I was trying to show you.

But anyway, since you have given up so quickly I will go back to my own coding.

Paul.



Ionic Wind Support Team

LarryMc

Paul,

Excuse the "bad hair" moment.  My wife is dragging me through menopause "kicking and screaming"! ;)
(It's either that or I have started the trip through my 2nd childhood)
Quotehdc = _CreateCompatibleDC(NULL)
Will give you a device context without confines, select the oversized bitmap into it and draw to your hearts content.  Then StretchBlt it into the paint DC.
That's the part I was missing AND in words I can understand.  Going back, it was in the MSDN docs but just not where I could understand what I was looking at.
QuoteThis isn't "C" type coding, it is Windows GDI programming
Hey, if it ain't EBasic I put it all in the "C" type coding bit bucket.  Just means I don't understand/like it.

At any rate, with your normal coding mastery, you have given me the help that I needed. 

Hope to have something for others to look at in a few days.

Thanks again,

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

LarryMc

UPDATE:

The 2 DC / 2 BITMAP scheme works perfectly.  It scales just the way I wanted it to work.

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

LarryMc

December 15, 2007, 10:07:27 PM #20 Last Edit: December 24, 2007, 05:01:56 PM by Larry McCaughn
Ran into a problem with my gage control that I can't seem to find the answer to.
Curious if anyone has seen something act like the attached.

watch the gages cycle between 0 and 5.  On the 10th cycle the graphics all go to black and white.

If I cycle between 0 and 10 it still takes the same amount of elapsed time for it to happen.(after the 5th cycle)

If I increase the number of gage controls it happens in fewer cycles.  If I decrease the number of controls it goes a little longer before it happens.

And it is not a random duration.  It repeats exactly.

Edit: Removed attachment and posted newer one below.

Larry

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

LarryMc

Believe I've found the problem.

I wasn't following the correct sequence to delete objects and clear handles for pens and brushes but was doing it correctly for regions and bitmaps.

The example quit displaying properly when it ran out of handles(or space for handles and their associated resources).

Now working on label and scale multiplier text.

Next will be figuring out how to properly display user defined scale range.

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

LarryMc

December 24, 2007, 05:00:36 PM #22 Last Edit: January 13, 2008, 07:58:50 AM by Larry McCaughn
Making some headway on my gage control.
Attached is an updated demo.

The following is how it is setup:openwindow main, 0, 0, 660, 500, @CAPTION|@SYSMENU, 0, "Test", &mainHandler
setwindowcolor(main, GetSysColor(15))
AddGage(main,"Gage 1","lbs/hr", 40,21,50,0,100,-1,1,1, GAGE1 )
AddGage(main,"Gage 2","oz", 220,21,100,0,100,0,7,2, GAGE2 )
AddGage(main,"Gage 3",chr$(34)+"H20", 431,21,150,0,100,0,11,3, GAGE3 )
AddGage(main,"Gage 4","psi", 80,221,200,0,100,0,13,4, GAGE4 )
AddGage(main,"Gage 5","feet", 280,221,250,0,100,0,8,5, GAGE5 )

SetGageDialDark(main,GAGE4)
SENDMESSAGE(main, GAGE_SETPANEL_COLOR, RGB(255,0,0),0, GAGE3)


And the gages are updated in a timer routine in the example: for x=gage1 to gage5
SENDMESSAGE main, GAGE_SETPOS, percent, 0, x
next x

Got some cleanup to do before releasing a beta library.

Larry

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

Haim

Hi,
this is very impressive indeed!
looks great.
can't wait to see the completed control.

haim

Dogge

Very Cool!
And impressive, looking forward to see more.

/Doug