Hi all,
This is my first post in this forum and although I always tried to learn by myself instead of asking at the first obstacle, right now I am absolutely blocked. I am a totally beginner with FireFly and even with PowerBasic. In fact I decided to purchase FF because coming from VB4, the lack of a form editor in PowerBasic made me think I will never progress with PB. Happily, FireFly come to the rescue and now I am able to write some small programs for personal use.
Now I am writing a program that collects data from 3 diferent test instruments through GPIB with a main control Window (form created in the FireFly IDE) that under user request creates new windows inside a class using the PowerBasic command "Graphic Window New" to plot the data acquired from the instruments.
The "Graphic Window New" function has a parameter that specifies the height and width of the window that is going to be created. I managed to change the Window Style to make it resizable with the mouse but now I need the graph that is plotted in that window to be plotted again to fit the new window dimensions if the user changes its size.
I suppose that in order to do that I need to write a function that is called when a WM_SIZE message is detected. The question is that as this plot window has not been created with a form in the FF Form Editor I don't know where the message loop for the plot window is located. So, where I should call the "Replot" function?
Could you give me some advice about this?
This is are some parts of the Class code:
Class cMeasurement
Instance MeasName As String
Instance PlotWidth As Long
Instance PlotHeight As Long
Instance PlotXPos As Long
Instance PlotYPos As Long
Instance hPlot As Long
Class Method Create()
MeasName = "Test of Plot Window."
PlotWidth=400
PlotHeight=400
PlotXPos=200
PlotYPos=200
End Method
Interface iMeasurement
Inherit IUnknown ' inherit the base class
Property Get MeasName As String
Property =Trim$(MeasName)
End Property
Property Set MeasName(Caption As String)
MeasName=Caption
End Property
Method Plot As Long
Graphic Window New MeasName, PlotXPos, PlotYPos, PlotWidth, PlotHeight To hPlot
Graphic Window Nonstable hPlot
ChangeWindowStyle( hPlot, %WS_OVERLAPPEDWINDOW )
Graphic Attach hPlot, 0 ', ReDraw
Graphic Box (0, 0) - (PlotWidth, PlotHeight), 0, %Red
Graphic Line (0, 0) - (PlotWidth, PlotHeight), %Red
Graphic ReDraw
'FF_Control_ShowState( hPlot, %SW_MAXIMIZE )
End Method
End Interface
End Class
And this is where the Class "Plot" function in a button click event in the main form is called:
'--------------------------------------------------------------------------------
Function FRMCONFIGMEASUREMENT_COMMAND1_BN_CLICKED ( _
ControlIndex As Long, _ ' index in Control Array
hWndForm As Dword, _ ' handle of Form
hWndControl As Dword, _ ' handle of Control
idButtonControl As Long _ ' identifier of button
) As Long
Measurement =Class "cMeasurement"
Dim Measurement As iMeasurement
Measurement.Plot
End Function
Any help and/or suggestion will be welcome.
Best regards.
Fran Dominguez
Fran,
Welcome to the forum!
First question for you... how many of these graphic windows might you open in an instance of your main program?
Hello Francisco.
There is a feature in firefly (Work space > Properties) to handle automatically the resizing of controls. See image below.
(https://www.planetsquires.com/protect/forum/index.php?action=dlattach;topic=3617.0;attach=1741;image)
Once the resizement is handled by the IDE, you only need to trap the WM_SIZE message of your
canvas, like this:
(https://www.planetsquires.com/protect/forum/index.php?action=dlattach;topic=3617.0;attach=1739;image)
Then, just add the re-plotting code in there.
The resizing rules are available to controls on FF generated forms (without some creative programming). I am trying to figure out what the needs of the program are so I can offer suggestions that will likely enable Francisco to use FF generated forms.
Yup.
(https://www.planetsquires.com/protect/forum/index.php?action=dlattach;topic=3617.0;attach=1743;image)
Sorry Elias, what I am saying is that right now, Francisco is using the PB statement "Graphic Window New" which creates (at runtime of course) a non-FF window (meaning no ResizeRules option). How many of these windows a user can launch per instance of the program is information I would like before recommending a FF-form-only solution.
If the answer is one, then he just creates one in FF and opens that form when the user asks for it. If the user can open multiple forms, then it might make sense to use FF's new feature that enables multiple instances of one form. With the second option there are some things you have to consider when creating multiple forms. I can go into more detail if needed.
There is a third option, to just enforce a maximum-number of these user launched forms and create a separate form for each possible instance. This option would mean the total cost to overhead would be overhead-of-one-form * Maximum-number-of-forms. Each instance of his program would incur that extra overhead even if the user only opened only one form. Not a very elegant option, in my opinion.
Thanks to everybody for your answers!!
Elias,
thanks for your suggestion. I already know how to resize and respond to WM_SIZE in a form created in the FF IDE but the forms I am talking about are created at runtime, not a design time.
David,
the program has not a fixed numbers of plots to be created, it depends on what measurements of the RF Power Amplifier under test the user is interested to get: Pout vs. Pin, Pout vs. Icc, Pout vs. Vbias, etc... That is the reason for me to not create the plot window in the form editor but with "Graphic New Window" function inside de "cMeasurement" Class, I don't know how many plots he is going to create.
The problem is that I don't know where to respond to messages of those runtime created windows as there is not the corresponding event manager function in the FF IDE at design time.
You can have a look at the main control window in the attached files (sorry I am not able to embed images in the post. Any hint?)
There is a ComboBox to select the X-Axis variable to act on and Y-Axis left and right measurement results to be acquired from instruments. Once you select the required plot/plots they are added in a ListView control. Once you finished to define what measurements you are interested in, a start button will call a function that will cycle through the ListView entries and will create "cMeasurement" object that will acquire the data and plot the results.
At the beginning of the software design phase I though about using MDI inside a tab to show all the measurements but as I started reading about MDI I realized it looked complicated for a beginner like me.
I suspect the way to act on those plot window messages is related to using DefWndProc and WndProc and if that is the case it loos too complicated for me and I'll have to search for a simpler solution. As I told, I am starting in the wonderful world of FF and PB and there are so many things to learn.....
Thank you for your support.
Fran Dominguez
Hi,
I am just starting to look at this. I expect that using the Firefly Graphic Control embedded on a Firefly Form would be easier, however you could try subclassing the GRAPHIC WINDOW:
Global hPlot As Dword
Function GraphicSubClassProc( ByVal hWndControl As Dword, _
ByVal wMsg As Dword, _
ByVal wParam As Long, _
ByVal lParam As Long _
) As Long
Select Case wMsg
Case %WM_SIZE
Static p As Long
Incr p
FF_Control_SetText HWND_FORM1, "wm_size" & Str$(p)
Case %WM_DESTROY
FF_SubClassEnd hWndControl
Exit Function
End Select
Function = FF_SubClassOrig( hWndControl, wMsg, wParam, lParam )
End Function
'--------------------------------------------------------------------------------
Function FORM1_COMMAND1_BN_CLICKED ( _
ControlIndex As Long, _ ' index in Control Array
hWndForm As Dword, _ ' handle of Form
hWndControl As Dword, _ ' handle of Control
idButtonControl As Long _ ' identifier of button
) As Long
Graphic Window New "Graph", 300, 300, 130, 130 To hPlot
Graphic Window Nonstable hPlot
'ChangeWindowStyle( hPlot, %WS_OVERLAPPEDWINDOW )
AfxAddWindowStyle hPlot, %WS_OVERLAPPEDWINDOW
FF_SubClassStart hPlot, CodePtr(GraphicSubClassProc)
Graphic Attach hPlot, 0 ', ReDraw
Graphic Box (0, 0) - (130, 130), 0, %Red
Graphic Line (0, 0) - (130, 130), %Red
Graphic ReDraw
End Function
Francisco,
I'm unsure if this will be helpful or not.
I wrote a program that also needed a plotting function (and sizes with the form). I was also collecting data and displaying it.
In this case it was created as a custom control that was added at run time (if a recall correctly ::) , it's been a while since I looked at it.)
Using that method I was able to send messages to it to change the scale, plot curves to it, etc.
Although I didn't use multiple forms, that method might be useful.
A sample program is near the bottom of this post. Called "fgrid".
http://www.planetsquires.com/protect/forum/index.php?topic=2020.0 (http://www.planetsquires.com/protect/forum/index.php?topic=2020.0)
Hi Paul,
thank you so much for your kind support and interest.
Quote from: TechSupport on January 08, 2015, 10:57:30 AM
Hi,
I am just starting to look at this. I expect that using the Firefly Graphic Control embedded on a Firefly Form would be easier, however you could try subclassing the GRAPHIC WINDOW:
Wow....maybe too much level for a not real programmer like me...Subclassing!!!
I must have a more detailed look trying to understand what you are suggesting.
Suppose I use a FireFly Graphic Control embedded on a FireFly Form, the problem here is I don't know at design time how many "graphic controls"/"Plots"/"Graphic Windows" will the user decided to get. Now the software works creating as many Graphic Windows as needed and I am able to Plot on it, the only problem I have is to "replot" the graph if the user decides to change the window graph dimension in order to have a more detailed look at the plot results.
I already wrote an application in FireFly 3.10 wich plots data acquired from serial port using a Power Basic Graphic embedded in the unique form the software has that has been created in the FF Form Editor.
The new software that I am writing now is by far more complicated: any number of GPIB converters can be used, you can assign the virtual Comm Port and GPIB address to each of the 3 instruments that are used and you can select any number of measurements you want.
Maybe the software architecture I decided to use for this application is not the best one and that is why I am asking for suggestion provided that:
1.- At design time it is unknown how many graphs are needed.
2.- The graphs should resizable.
3.- The graphs should respond to WM_CONTEXTMENU messages in order to the user can save the graph plots or measurement data to disk.
The only options that crossed my mind were:
1.- Create an MDI form as a child of a Tab control in the Main program control form. I don't know if windows allows that.
2.- Create as many Graphic Windows as the user requests.
3.- Create an MDI window separated from the Main program control form. But I still have the same problem of know where the message loop of the MDI window is located with the added complexity of using MDI.
What do you think? Is there a more obvious approach I overlooked?
Best regards.
Fran
Hi Robert,
thanks for answering.
QuoteI'm unsure if this will be helpful or not.
Any comment is helpful by itself because it makes me to learn the way someone solves their problems.
QuoteIn this case it was created as a custom control that was added at run time (if a recall correctly ::) , it's been a while since I looked at it.)
Something similar is what I done creating a Custom Control with a PB Graphic Control embedded in FF3.10. I was plotting the 1000 RF power samples per second sent via serial port from a RF Power Meter I designed. Have a look at the attached file. I think both you and I, used similar approach to plot the results of our RF test instruments.
I see you also work with RF Instruments...
Quote
A sample program is near the bottom of this post. Called "fgrid".
http://www.planetsquires.com/protect/forum/index.php?topic=2020.0 (http://www.planetsquires.com/protect/forum/index.php?topic=2020.0)
Nice interface.....I see you used Log freq axis. Maybe EMC measurements?
Once again. Thank you so much for the link with your source code and comments.
Best regards.
Fran
Hi Francisco,
You're right. It was for some EMC testing for microphones. The program drives an RF generator through a GPIB port and the signals are returned using and Audio Precision analyser.
However, most of what I do is audio frequency range. I've used that control since in a production test fixture.
Hi Fran,
I am putting together a little example project to show one way of creating a multiple form project for all of your spawned graphic windows. I am using Jose's CGDIPlus.inc class for GDI+ along with Firefly's built in GraphicControl (which is also based on Jose's graphic control). Using these tools you will have full control over form resizing without subclassing. I'll post it as soon as it's done so others can jump in with comments. I don't normally create programs with GraphicControl stuff so others will probably be better equipped to critique my approach.
That will be cool Paul! :)
Hi Paul,
QuoteI am putting together a little example project to show one way of creating a multiple form project for all of your spawned graphic windows.
Wondeful but...take care!! Otherwise we can get used to someone to do our homework. ;)
Jokes apart, that will be a great help. Thanks again.
Anyway as my goal is to learn I will investigate and try some code "playing" with DefWndProc and WndProc as I think that it can be an aproach as well. Am I right?
Best regards.
Fran
Hi Fran,
Sorry it took so long to respond. Life got in the way :)
I have attached an extremely simplistic project to demonstrate one way to (hopefully) solve your problem.
Here are a few things that I did that you should pay attention to:
- I am using Firefly's built in GraphicControl.
- I am using GDI+ to do the drawing rather than PB's GRAPHIC commands. To accomplish this I am using Jose's GDI+ classes. You simply need to #INCLUDE Once "CGDIPlus.inc" at the top of the source code (or in FF_APPSTART). Jose's GDI+ Help file can be found at: http://www.planetsquires.com/protect/forum/index.php?topic=3597.0
- I am using a simple TYPE structure to hold the measurement information and then dynamically creating a block of memory to represent that TYPE (using FF_MemAlloc).
- I am using the PB functionality to "DIM...AT". This is a powerful technique that allows me to overlay the dynamically created memory block with whatever structure I wish. Accessing TYPE elements is then very easy.
- I create the popup/resizable frmGraphics Form (non-modal) and pass the memory block handle to WM_CREATE via the UserData parameter. I store that memory handle in the Form for later use via the WinAPI functions SetProp, GetProp and RemoveProp.
- The frmGraphics Form contains one GraphicControl that is automatically resized using the "ResizeRules" property.
- The GraphicControl is set to "Stretchable" so that when the Form is resized, the graphic will also resize proportionally.
- You need to use the GetDlgItem api to retrieve the GraphicControl HWND handle rather than using FF's auto created HWND' (via the F4 window). This is because multiple instances of that control can exist at any one time.
Please let me know if any of this is unclear. The program does a LOT in a very few number of lines. Using dynamically created memory is probably not very "BASIC-like" but it certainly simplifies the design. No need to have global arrays or classes/collections, etc.
Francisco,
Quote from: Francisco DomÃnguez Latorre on January 08, 2015, 12:24:35 PM
1.- At design time it is unknown how many graphs are needed.
2.- The graphs should resizable.
3.- The graphs should respond to WM_CONTEXTMENU messages in order to the user can save the graph plots or measurement data to disk.
Paul addressed the first two items in his demo. Inserting the code below into the bottom of the frmGraphic (from Paul's demo project in his last post) will show how to implement item number three in FF. Although you could use a WndProc, as you suggested, I hope you can see that FF can do it much easier with built-in functionality.
Enum ContextMenuID
Save = 1501
Print
End Enum
'--------------------------------------------------------------------------------
Function FRMGRAPHIC_WM_COMMAND ( _
hWndForm As Dword, _ ' handle of Form
hWndControl As Dword, _ ' handle of Control
wNotifyCode As Long, _ ' notification code
wID As Long _ ' item, control, or accelerator identifer
) As Long
Select Case wID
Case %ContextMenuID.Save 'Context menu selection
MsgBox "Save Data for:" & Str$(GetProp(hWndForm,"MEMHANDLE"))
Case %ContextMenuID.Print
MsgBox "Print Data for:" & Str$(GetProp(hWndForm,"MEMHANDLE"))
End Select
End Function
'--------------------------------------------------------------------------------
Function FRMGRAPHIC_WM_CONTEXTMENU ( _
hWndForm As Dword, _ ' handle of Form
xPos As Long, _ ' x-coordinate of cursor
yPos As Long _ ' y-coordinate of cursor
) As Long
Local hPopup As Long
Menu New PopUp To hPopup
Menu Add String, hPopUp, "Save Data" , %ContextMenuID.Save , %MF_ENABLED
Menu Add String, hPopUp, "Print Data" , %ContextMenuID.Print, %MF_ENABLED
TrackPopupMenu hPopup,%TPM_LEFTALIGN Or %TPM_RIGHTBUTTON, _
xPos, yPos, 0, hWndForm, ByVal 0
End FunctionWe didn't do all your homework... :) just enough to get over the learning curve (hopefully anyway).
David
Paul,
Took so long to respond??? Are you joking? Next day answer with custom code...Yes! You are joking.
I would like to make some comments. I am sorry because it is a bit, how to say, boring, dense,...?
1.- I see you dimensioned Measurement(0) both in the frmMain and frmGraphic with "Dim Measurements(0) As MEASUREMENT_TYPE At hMemHandle"
What is the scope of this variable? Local to each function?
2.- SetProp API call is very interesting, it looks it allows to store some user data into any window without declaring or using Global variables. In this case the Window Property "MEMHANDLE" is created in the Main Window which stores the MemHandle of the Graphic Data Structure allocated in memory. Clever approach!! So many things to learn....
3.- One of the most important lesson I learned from your code is that frmGraphic_Show(hWndParent,ShowModalFlag, UserData) instantiates a new window of an already created form in the Form Editor and returns the handle of the new created window, this makes available to the programmer the message loop function of all the created new windows. I think it doesn't matter if I use GDI+, PB Graphic functions or OpenGL, I can respond to events in every new window created.
This frmNAME_Show functions are too important to trust on my memory and digging in old code or in the help file to remember it exists and how to use it when I need it. As a ocasional programmer I need a way to quickly get an overview of the most common functions.
I will create and entry in the Functions Library manager with big red blinking font....Hell!! I cannot use big red blinking font in the Function Library Manager. ;)
IMHO, the text in the FF Help File was not enough detailed because it states that:
"Every Form in FireFly has code generated that you can call to display that Form" and "For example, to show a Form called "MyForm", you would call the following from within your code:"
Because of this both statements I thought this kind of functions will only DISPLAY an already created form although I should had a more detailed look at what is also said: "The function will return the Window handle of the newly created Form."
Anyway as a novice programmer in FF and being a non native English speaker all of this was not enough clear for me. Luckily it has been perfect clarified thanks to your code.
4.- Another important think I learned is that GDI+ is too much for me. During this days I have been reading the GDI+ Help File from Jose Roca and I was overwhelmed...about 600 functions, 40 classes, wrappers, etc.... What a huge work from Jose Roca!!!
I am still getting used to PB and FF with all its functions, starting to use some API functions, etc, so sincerely I don't think I am ready for GDI+ at this moment.
In fact, as I am simply need 2D plots, without alpha channels, bezzier curves, etc and because PB DDT Graphic commands are so simple to use and perform so well I insisted on integrating them in the FF application.
Regarding your sample code with GDI+ you are resizing the Graphic Control but you are not replotting the "data". When you make the window bigger, the lines also get thicker, it's like a zooming on a low resolution BMP.
I have been trying to replot the data on the WM_SIZE but I have not been able even to "clear" the plot before drawing the new data with GraphCtxClear.
5.- Regarding your comments about GetDialogItem, in the demo I created I stored the Graphic Handle in a form property for every new window created but Is a good point to remember in the future. Thanks for the lesson.
6.- After severals failed attempts to use DefWndProc, WndProc and CallWndProc I realized that all of that is managed by FireFly Subclassing functions. That is the way I decided to "intercept" the messages from instances of the same form.
Regarding this I read somewhere that all the instances of the same window class share the same Customized Window Procedure and I checked that is true, after printing on every created form the CODEPTR(GraphicFunctionProc) defined by me.
Who manages all the details when the GraphicFunctionProcedure is defined on every form created on runtime? FF Code Generator or PB Compiler?
What will happen when I declare the function inside an object of a user defined class?
Robert,
1.- Thanks for the information about your program and the source code. I asked about RF because of the screen capture I saw in your FF forum post http://www.planetsquires.com/protect/forum/index.php?topic=2020.0 (http://www.planetsquires.com/protect/forum/index.php?topic=2020.0) but after compiling your source code I realized it is not the same.
The screen capture in the mentioned post show it is "RF Scan" from "EV". Can you give me a link to that software or company that created it?
2.- After looking inside your code I saw you used some API calls (MoveTo, LineTo) to draw on the form, managed by yourself device contexts, etc, etc....That is too advanced programming for me.
After some time I realized your code was out of my reach although the graphic result behavior was exactly what I needed.
This make me focus on "integrating" DDT Graphic Functions in FireFly as my main goal.
3.- One of the reason for me to move to FireFly was the complication of form creation in PowerBasic. I tried PBForms with PB and is good for small applications but when you want to create and "advanced" user interface things start to get more and more difficult to manage for a beginner comming from VB4 because of all that message loop stuff, callbacks, etc.
Firefly allows me to create a control and on design time define its size an position on the form before compiling and see how it looks. That is why I want to have a control or at least a container for a graphic control that is "watchable" in the form editor.
David,
1.- as now the approach is slightly different because I managed to embed a PB graphic control insisde a FF Custom Control in a form with buttons, labels, etc, I can use buttons to trigger several different actions, anyway as I have learned how to intercept the window messages in a "runtime" created window it is easy to respond to the context messages and to others.
In fact, now the graphic is resized and replotted responding to WM_SIZE but it is not when I maximize the window. I'll have to investigate what is the message sent in that case.
2.- Well...you didn't do my homework but you gave me the pencil, paper and more than a starting point. I hope the result is at the same level as the given help. ;)
I would like to share with all of you and with the FireFly community what I learned thanks to all of you and I will appreciate your comments, corrections or suggestions about the source code attached to this mail.
Finally I would like to apologize for this so extensive post and once again express my gratitude for your help and your time
Best regards.
Fran
Francisco,
The RF scan program is mine. In that program the GUI was written in VB6 but the drawing routines were done with a PB dll (data was passed to a VB6 picturebox).
So my goal was with similar, future programs, to be able to do that without the VB6 component, which I did.
In the final version I support up to 32 curves (more than that gets too cluttered).
You fill an array with the level and frequency points for each curve as well as the curve color and line width for each curve.
These programs are of course used at my work. I work for Bosch, and EV (ElectroVoice), is one of the brands.)
Quote from: Francisco DomÃnguez Latorre on January 13, 2015, 01:59:52 PM
1.- I see you dimensioned Measurement(0) both in the frmMain and frmGraphic with "Dim Measurements(0) As MEASUREMENT_TYPE At hMemHandle"
What is the scope of this variable? Local to each function?
The scope is local because I used
DIM inside of a sub/function.
Quote
2.- SetProp API call is very interesting, it looks it allows to store some user data into any window without declaring or using Global variables. In this case the Window Property "MEMHANDLE" is created in the Main Window which stores the MemHandle of the Graphic Data Structure allocated in memory. Clever approach!! So many things to learn....
There are many things that can make programming easier for you if you use the WinAPI directly. Never be afraid to use it regardless of what the fear mongering anti-WinAPI people tell you :)
Quote
4.- Another important think I learned is that GDI+ is too much for me. During this days I have been reading the GDI+ Help File from Jose Roca and I was overwhelmed...about 600 functions, 40 classes, wrappers, etc.... What a huge work from Jose Roca!!!
I am still getting used to PB and FF with all its functions, starting to use some API functions, etc, so sincerely I don't think I am ready for GDI+ at this moment. Using the FireFly GraphicControl with GDI functions is easy to do as well.
If GDI+ is too overwhelming then you still have the option of using the simpler GDI functions. I expect that the GDI functions is what the PB GRAPHIC statements use. Jose has a help file for thos functions as well! Check out his GDI.chm help file.
Quote
Regarding your sample code with GDI+ you are resizing the Graphic Control but you are not replotting the "data". When you make the window bigger, the lines also get thicker, it's like a zooming on a low resolution BMP.
I have been trying to replot the data on the WM_SIZE but I have not been able even to "clear" the plot before drawing the new data with GraphCtxClear.
I never focused on the graphic plotting but simply made the graphic resizable. You're right, I should have used an approach to clear the graphic and then re-plot the graphic based on the new size.
Quote
5.- Regarding your comments about GetDialogItem, in the demo I created I stored the Graphic Handle in a form property for every new window created but Is a good point to remember in the future. Thanks for the lesson.
I downloaded your sample code project and you have made this error several times in your code GraphicSubClassProc. You will notice that when you create several of your resizable graphic forms (and then use your mouse to resize them) that the wrong controls will be acted on. For multiple instanced forms you should *never* rely on the FireFly generate HWND_* variables. You should always use the GetDlgItem(HWND_*, IDC_*) approach.
I also find it very confusing to add a GRAPHIC WINDOW to a CUSTOMCONTROL of a FORM. Too many sub-windows to keep track of. :) I'm thinking that it would be easier for you to bypass the CustomControl altogether and simply add the GRAPHIC WINDOW to the FORM directly in the Form's WM_CREATE??? Or better yet, just use the FF Graphiccontrol with GDI functions :)
Quote
Who manages all the details when the GraphicFunctionProcedure is defined on every form created on runtime? FF Code Generator or PB Compiler?
What will happen when I declare the function inside an object of a user defined class?
I am not 100% sure I understand the question. Subclassing simply intercepts messages destined for your window prior to it being sent to the default message procedure for that window. In the subclass, you can modify what you want to happen prior to the window/control receiving the message. In most cases you will eventually want the message to be directed to the default procedure otherwise Windows itself may act funny. That's all the FireFly subclass wrappers do: It allows you to specify a function where you can put code to act on messages prior to them being sent to the default message procedure of window. FireFly generates all of the necessary code.
Not sure if you can define the GraphicFunctionProcedure function in a Class. Does CODEPTR work on a function within a Class? Not sure. If you can get the address of the function (via CODEPTR) then the Class approach should work. I haven't tested this though.
> What will happen when I declare the function inside an object of a user defined class?
That won't work.
Methods in a class have a hidden parameter, generally know as "this", that is the address of a pointer to the class virtual table. Windows will call the method without passing the "this" parameter and it will crash.
In the past years, some PBer's have tried to do it and, of course, they have failed miserabily.
Paul,
your comments are much appreciated.
QuoteThere are many things that can make programming easier for you if you use the WinAPI directly. Never be afraid to use it regardless of what the fear mongering anti-WinAPI people tell you (https://www.planetsquires.com/protect/forum/Smileys/default/smiley.gif)
You are right. I am realizing about that, but it is a hard way because so many functions to learn besides the ones of the language in use. Good advice.
QuoteIf GDI+ is too overwhelming then you still have the option of using the simpler GDI functions. I expect that the GDI functions is what the PB GRAPHIC statements use. Jose has a help file for thos functions as well! Check out his GDI.chm help file.
Yes, I also read about GDI, looks simpler and more than enough for what I need. The problem are not the functions by itself but the uses of several classes, initialization and all that stuff. I recently discovered the wonderful use of classes and how can ease my work but one thing is write a class with a couple of properties and methods and a different thing is directly jump to GDI+.
I'll give GDI an opportunity for this application.
QuoteI downloaded your sample code project and you have made this error several times in your code GraphicSubClassProc. You will notice that when you create several of your resizable graphic forms (and then use your mouse to resize them) that the wrong controls will be acted on. For multiple instanced forms you should *never* rely on the FireFly generate HWND_* variables. You should always use the GetDlgItem(HWND_*, IDC_*) approach.
Paul, initially I follow you suggestion of using GetDlgItem but I always got "0" as the handle of the Custom Control. I don't know if the reason is because it is "associated" with the PB Graphic Dialog/Control but it didn't work. Have a look, this is the code:
hCustomControl=GetDlgItem (hWndControl,IDC_FORM2_CUSTOMCONTROL1)
Select Case wMsg
Case %WM_SIZE
ztrace "Entering into message loop."
hGraphic=GetProp(hWndControl,"HGRAPHIC")
Graphic Clear
'Control Kill hCustomControl,IDC_FORM2_CUSTOMCONTROL1 'IMPORTANT!!! The Control Owner is not the Form but the CustomControl handle.
Control Kill HWND_FORM2_CUSTOMCONTROL1,IDC_FORM2_CUSTOMCONTROL1 'IMPORTANT!!! The Control Owner is not the Form but the CustomControl handle.
'****************************
'* HANDLE OF CUSTOMCONTROL GIVES 0 IF GOT WITH GETDLGITEM
'****************************
ztrace "Custom Control Handles:"+str$(hCustomControl)+Str$(HWND_FORM2_CUSTOMCONTROL1)
QuoteI also find it very confusing to add a GRAPHIC WINDOW to a CUSTOMCONTROL of a FORM. Too many sub-windows to keep track of.
Yes, it is very confusing also for me but it is the way you suggested in this forum some time ago before the FF Graphic Control was included in FF. Regarding hadles I have no idea about what is really happening inside the program with this approach.
QuoteI'm thinking that it would be easier for you to bypass the CustomControl altogether and simply add the GRAPHIC WINDOW to the FORM directly in the Form's WM_CREATE???
The problem is that as I come from VB4 I am not used to create controls in a form in runtime. I like to design the form in the form editor and knowing exactly the phisical space they need and place the buttons, labels and other controls in the proper positions.
When you said "GRAPHIC WINDOW" you mean to use GRAPHIC WINDOW NEW PB function? I asked this because that funcion creates a NEW window not a child window of the current form.
QuoteOr better yet, just use the FF Graphiccontrol with GDI functions
I agree with you, this will be the way. I will move to SDK programming even before having enough skills in Windows programming :)
I read somewhere that GDI+ is slower than GDI because starting with Win7 GDI is hardware accelerated while GDI+ is not. Do you think it is true? It doesn't matter for my plots, it is just curiosity.
Anyway independently of if I use PB Graphic functions, GDI or GDI+ I am learning so much from this post and forum thanks to FireFly.
QuoteI am not 100% sure I understand the question. Subclassing simply intercepts messages destined for your window prior to it being sent to the default message procedure for that window. In the subclass, you can modify what you want to happen prior to the window/control receiving the message. In most cases you will eventually want the message to be directed to the default procedure otherwise Windows itself may act funny. That's all the FireFly subclass wrappers do: It allows you to specify a function where you can put code to act on messages prior to them being sent to the default message procedure of window. FireFly generates all of the necessary code.
What I mean is that I declared the function in the Form2 and I created several instances of Form2.
As all the windows of a registered class share the same window procedure and as I have (or at least is what I think) the GraphicFunctionProcedure existing in every Form2 window.
Is the GraphicFunctionProcedure function existing for each window although only the address of that function is associated to the class window Form2 belongs to?
Which of those addresses of the GraphicFunctionProcedure is associated with the Form2 Window Class? The first time I subclass the Form2? The last time?
I am trying to guess what will happend when the function is declared and called in every instance of a Form. Not because I want to do that but because I would like to learn the internals of Windows/FireFly/Compiler.
QuoteNot sure if you can define the GraphicFunctionProcedure function in a Class. Does CODEPTR work on a function within a Class?
I will try this morning as a learning task.
Is CODEPTR function getting the address of the function at compiling time or in running time?
What is happening in my application? Because in every Form2 instance I get exactly the same GraphicFunctionProcedure address.
Could you be so kind to have a look inside the code in order to know why I am getting a "0" with hCustomControl=GetDlgItem (hWndControl,IDC_FORM2_CUSTOMCONTROL1)
Thank you so much for your time and support.
Best regards.
Fran
Jose,
thanks for answering.
I would like to take the chance to express you my gratitude for all your support and contributions to PB and FF with all those WinApiHeader, GDI and GDI+ stuff. And all for free!!!
I am very proud we have in Spain so skilled people that offer they help without any other interest.
Quote from: Jose Roca on January 13, 2015, 06:58:46 PM
> What will happen when I declare the function inside an object of a user defined class?
That won't work.
Methods in a class have a hidden parameter, generally know as "this", that is the address of a pointer to the class virtual table. Windows will call the method without passing the "this" parameter and it will crash.
In the past years, some PBer's have tried to do it and, of course, they have failed miserabily.
So, what will be the path? Maybe defining the function in the main form or in a module and passing the address of the GraphicWndProc to a property in the class?
If several objects of the same class are instantiated what will happen if I set the property for each object?
Let suppose that each object has its own thread for both taking measuring from the Test Instruments and for processing messages of each window created in every class objects. In this case every window will need the address of the GraphicWndProc. What is the proper way to do this?
Best regards.
Fran
Francisco,
I modified your second project post to get rid of the PB DDT graphics. I think you will like the results.
Quote from: David Kenny on January 07, 2015, 10:20:43 PM
If the user can open multiple forms, then it might make sense to use FF's new feature that enables multiple instances of one form. .
Sorry, this was referring to a new feature that was implemented in the FF Dot syntax preview a while back. We will have to wait until it is released to take advantage of it. Right now, the GetDlgItem method of getting the control handles is a good way of handling multiple instances of a FF form. If you need Static variables in this context, you will need to take care of that yourself also. I have a method I use if anyone is interested.
David