Hello,
Sorry but I posted this in the wrong place before. Not wide awake yet.
I've been trying to work on a program based on Jose's CWindow with TAB example in CSED.
After a lot of errors and now a really hung cpu, I've narrowed my problem down to when I
add a button on the main form and there is a button on a tab page. I can press the main form
button & no problem. Press the tab page button and my cpu sits near 100 percent usage.
Will somebody please tell me what I'm doing wrong?
Thanks.
' ########################################################################################
' Microsoft Windows
' File: CW_TabCtrl.pbtpl
' Contents: Template - CWindow with a tab control
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.03+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#COMPILE EXE
#DIM ALL
'#DEBUG ERROR ON
'#DEBUG DISPLAY ON
#TOOLS OFF
%UNICODE = 1
' // Include files for external files
#INCLUDE ONCE "CWindow.inc" ' // CWindow class
#INCLUDE ONCE "TabCtrl.inc" ' // Tab control wrappers
#INCLUDE ONCE "ComboBoxCtrl.inc" ' // Combo box control wrappers
#INCLUDE ONCE "ListBoxCtrl.inc" ' // List box control wrappers
' // Control identifiers
%IDC_TAB = 1001
%IDC_EDIT1 = 1002
%IDC_EDIT2 = 1003
%IDC_BTNSUBMIT = 1004
%IDC_COMBO = 1005
%IDC_LISTBOX = 1006
%IDC_BTNMAIN = 1007
' ========================================================================================
' Main
' ========================================================================================
FUNCTION WINMAIN (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG
' // Set process DPI aware
' SetProcessDPIAware
TRACE NEW "trc.txt"
TRACE ON
' // Create an instance of the class
LOCAL pWindow AS IWindow
pWindow = CLASS "CWindow"
IF ISNOTHING(pWindow) THEN EXIT FUNCTION
' // Create the main window
' // Note: CW_USEDEFAULT is used as the default value When passing 0's as the width and height
pWindow.CreateWindow(%NULL, "CWindow with a Tab control", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
' // Change the class style to remove flicker
pWindow.ClassStyle = %CS_DBLCLKS
' // Set the client size
pWindow.SetClientSize 520, 445
' // Center the window
pWindow.CenterWindow
' // Add a Tab control
LOCAL hTab AS DWORD
hTab = pWindow.AddTab(pWindow.hwnd, %IDC_TAB, "", 10, 10, 490, 303)
pWindow.AddButton(pWindow.hwnd, %IDC_BTNMAIN, "Main", 15, 335, 116, 41, %BS_PUSHBUTTON)
' // Add tab pages
LOCAL pTabPage1, pTabPage2, pTabPage3 AS IWindow
pTabPage1 = pWindow.InsertTabPage(hTab, 0, "Tab 1", -1, 0, 0, CODEPTR(TabPage1_WndProc))
pTabPage2 = pWindow.InsertTabPage(hTab, 1, "Tab 2", -1, 0, 0, CODEPTR(TabPage2_WndProc))
pTabPage3 = pWindow.InsertTabPage(hTab, 2, "Tab 3", -1, 0, 0, CODEPTR(TabPage3_WndProc))
' // Add controls to the first page
pWindow.AddLabel(pTabPage1.hwnd, -1, "First name", 15, 15, 121, 21)
pWindow.AddLabel(pTabPage1.hwnd, -1, "Last name", 15, 50, 121, 21)
pWindow.AddTextBox(pTabPage1.hwnd, %IDC_EDIT1, "", 165, 15, 186, 21)
pWindow.AddTextBox(pTabPage1.hwnd, %IDC_EDIT2, "", 165, 50, 186, 21)
pWindow.AddButton(pTabPage1.hwnd, %IDC_BTNSUBMIT, "Submit", 340, 185, 76, 26, %BS_PUSHBUTTON)
' // Add controls to the 2nd page
LOCAL hComboBox AS DWORD
hComboBox = pTabPage2.AddComboBox(pTabPage2.hwnd, %IDC_COMBO, "", 20, 20, 191, 105)
' // Add controls to the 3rd page
LOCAL hListBox AS DWORD
hListBox = pTabPage3.AddListBox(pTabPage3.hwnd, %IDC_LISTBOX, "", 15, 20, 161, 120)
' // Fill the controls with some data
LOCAL i AS LONG
FOR i = 1 TO 9
Combobox_AddString hComboBox, "Item" & STR$(i)
ListBox_AddString hListBox, "Item" & STR$(i)
NEXT
ComboBox_SetCurSel hComboBox, 0
ListBox_SetCurSel hListBox, 0
' // Display the first tab page
ShowWindow pTabPage1.hwnd, %SW_SHOW
' // Set the focus to the first tab
TabCtrl_SetCurFocus hTab, 0
' // Default message pump (you can replace it with your own)
pWindow.DoEvents(nCmdShow)
TRACE CLOSE
END FUNCTION
' ========================================================================================
' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
STATIC hInstance AS DWORD ' // Instance handle
STATIC lpc AS CREATESTRUCT PTR ' // Pointer to the creation parameters
STATIC pWindow AS IWindow ' // Reference to the IWindow interface
' // Process window mesages
SELECT CASE uMsg
CASE %WM_CREATE
' // Pointer to the creation parameters
lpc = lParam
' // Instance handle
hInstance = @lpc.hInstance
' // Get a reference to the IWindow interface from the CREATESTRUCT structure
pWindow = CWindow_GetObjectFromCreateStruct(lParam)
EXIT FUNCTION
CASE %WM_COMMAND
SELECT CASE LO(WORD, wParam)
CASE %IDCANCEL
' // If the Escape key has been pressed...
IF HI(WORD, wParam) = %BN_CLICKED THEN
' // ... close the application by sending a WM_CLOSE message
SendMessage hwnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
CASE %IDC_BTNMAIN
MSGBOX "btn main"
EXIT FUNCTION
END SELECT
CASE %WM_DESTROY
' // End the application
PostQuitMessage 0
EXIT FUNCTION
CASE %WM_NOTIFY
LOCAL nPage AS DWORD ' // Page number
LOCAL pTabPage AS IWindow ' // Tab page object reference
LOCAL tci AS TCITEM ' // TCITEM structure
LOCAL ptnmhdr AS NMHDR PTR ' // Information about a notification message
ptnmhdr = lParam
SELECT CASE @ptnmhdr.idFrom
CASE %IDC_TAB
SELECT CASE @ptnmhdr.code
CASE %TCN_SELCHANGE
' // Show the selected page
nPage = TabCtrl_GetCurSel(@ptnmhdr.hwndFrom)
tci.mask = %TCIF_PARAM
TabCtrl_GetItem(@ptnmhdr.hwndFrom, nPage, tci)
IF tci.lParam THEN
pTabPage = Ptr2Obj(tci.lParam)
IF ISOBJECT(pTabPage) THEN
ShowWindow pTabPage.hwnd, %SW_SHOW
pTabPage = NOTHING
END IF
END IF
CASE %TCN_SELCHANGING
' // Hide the current page
nPage = TabCtrl_GetCurSel(@ptnmhdr.hwndFrom)
tci.mask = %TCIF_PARAM
TabCtrl_GetItem(@ptnmhdr.hwndFrom, nPage, tci)
IF tci.lParam THEN
pTabPage = Ptr2Obj(tci.lParam)
IF ISOBJECT(pTabPage) THEN
ShowWindow pTabPage.hwnd, %SW_HIDE
pTabPage = NOTHING
END IF
END IF
END SELECT
END SELECT
END SELECT
' // Pass unprocessed messages to Windows
FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Tab page 1 window procedure
' ========================================================================================
FUNCTION TabPage1_WndProc (BYVAL hWnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
SELECT CASE uMsg
CASE %WM_COMMAND
SELECT CASE LO(WORD, wParam)
CASE %IDC_BTNSUBMIT
IF HI(WORD, wParam) = %BN_CLICKED THEN
MSGBOX "Submit"
EXIT FUNCTION
END IF
END SELECT
END SELECT
FUNCTION = DefWindowProc(hWnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Tab page 2 window procedure
' ========================================================================================
FUNCTION TabPage2_WndProc (BYVAL hWnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
LOCAL hBrush AS DWORD
LOCAL rc AS RECT
LOCAL tlb AS LOGBRUSH
SELECT CASE uMsg
CASE %WM_ERASEBKGND
GetClientRect hWnd, rc
' Create custom brush
tlb.lbStyle = %BS_SOLID
tlb.lbColor = &H00CB8734???
tlb.lbHatch = 0
hBrush = CreateBrushIndirect(tlb)
' Erase background
FillRect wParam, rc, hBrush
DeleteObject hBrush
FUNCTION = %TRUE
EXIT FUNCTION
END SELECT
FUNCTION = DefWindowProc(hWnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Tab page 3 window procedure
' ========================================================================================
FUNCTION TabPage3_WndProc (BYVAL hWnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
LOCAL hBrush AS DWORD
LOCAL rc AS RECT
LOCAL tlb AS LOGBRUSH
SELECT CASE uMsg
CASE %WM_ERASEBKGND
GetClientRect hWnd, rc
' Create custom brush
tlb.lbStyle = %BS_SOLID
tlb.lbColor = %GREEN
tlb.lbHatch = 0
hBrush = CreateBrushIndirect(tlb)
' Erase background
FillRect wParam, rc, hBrush
DeleteObject hBrush
FUNCTION = %TRUE
EXIT FUNCTION
END SELECT
FUNCTION = DefWindowProc(hWnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
For the moment, I would welcome a response from anybody.
Either way == yes they also see the problem or no the program works fine for them.
Or that I'm a fool for posting in the wrong forum.
Until I get some sort of response, I can't see moving forward with the program ( which is much bigger
than the posted code ... it was just the smallest program that deomonstrated my problem and I had
spent a few days trying different options and removing code to see what could be causing the
problem ).
I have been looking at the problem but I haven't found the cause so far. For the moment, you can use SDK code to add the tab control and create the pages and controls displayed in the pages.
Thanks for the reply.
I'll continue on using your CWindow code and just disable the few buttons that are causing me problems.
Checkboxes & option buttons aren't causing any problems. Just the pushbuttons.
I can add a couple small buttons on the main form if needed until you find the problem.
So far I haven't used pure SDK to create any programs as my needs have been satisfied by DDT or
Phoenix or FireFly. Maybe I'll do the next program in SDK if I get bored with CWindow.
José,
I don't know if I'm seeing it right or not but while running in the debugger & animating it seems to be
skipping over the Unicode sections of code and stepping thru the ansi sections. Unless some of the
#IF are doing #IF NOT %DEF(%UNICODE) first instead of #IF %DEF(%UNICODE). AFXWIN.INC has
the #IF backwards!!!???
Also AFXPATH.INC has them backwards???
Is there a way to undef the %UNICODE = 1 ?
I was running in animate for about half-an-hour and it still hadn't shown any form on screen.
Is this normal? Admittedly I'm runing Windows 2000 on a P4 2.8 and on a slow hd.
Those 2 inc files still look wrong but they aren't the whole problem.
AFXWIN.INC line 3898
#IF NOT %DEF(%UNICODE)
MACRO AfxGetMessageFontPointSize = AfxGetMessageFontPointSizeW
#ELSE
MACRO AfxGetMessageFontPointSize = AfxGetMessageFontPointSizeA
#ENDIF
I changed them & compiled tabbtn.bas but it still maxed my cpu.
I'll check back in the morning ( my time which will be around 12:00 noon here ).
The only way to udenf %UNICODE = 1 is to no define it. REM or remove it.
I have wronly used #IF NOT %DEF, instead of #IF %DEF, in AfxWin.inc and AfxPath.inc. The attachment below contains these two files modified.
I took a quick look thru checking that there was a W & an A in the #IF %DEF lines and
found a few that you might want to look at. It's the .inc file & line # of the #IF.
I've gotten down to TabCtrl.inc and that's about 2/3 the way thru the list.
I'll continue on just to be doing something and check back in an hour or so.
I'm not changing anything. Just looking.
advpub 208
bthdef 1142
1152
cfgmgr32 2567 ? spelling
commctrl 1281
dbghelp 2917
richedit 1170
rpcdce 930
1691
setupapi 821
3772
5425
5439
5463 & more no #ELSE
shlwapi 204
811
822
2415
Only found 3 more that need checking.
That's amazing considering the thousands of lines that needed changes ( or was it hundreds of
thousands ? ).
wincrypt 16233
wininet 2143
winreg 1003
Thanks very much. The attached fie contains the modified include files.
BTW the ones lacking #ELSE were functions that had not both A and W versions, and there is a funny one:
' StrFormatByteSize64 can be used for either ANSI or Unicode characters. However, while StrFormatByteSize64A
' can be called directly, StrFormatByteSize64W is not defined. When StrFormatByteSize64 is called with a
' Unicode value, StrFormatByteSizeW is used.
#IF %DEF(%UNICODE)
MACRO StrFormatByteSize64 = StrFormatByteSizeW
#ELSE
MACRO StrFormatByteSize64 = StrFormatByteSize64A
#ENDIF
Thank YOU very much. I can't begin to realize how much time & effort you have put into
creating these files.
But my original problem still exists. Any clues as to what I'm doing wrong?
No real rush as I can work around it. I'm going to have to take a few hours off and
let my eyes rest from squinting at all those lines ( forgot to check if there was a way
to increase the font size in the program I was using .. there was but it wasn't on the main
menu bar ).
José,
Any progress? Or even a hint at what I'm doing wrong?
I don't want to keep you from doing other work.
My temporary solution is to put the buttons on the main form but I don't like the look.
They look much better on the tab page.
Found out I don't even have to push the tab button. Just tabbing between controls and
landing on the button will max out my cpu.
Once again THANKS!
José,
Any hint of the problem yet?
I do not mean to rush you as I know you've been hard at work getting your headers
compatible with the PB headers. And putting together sample programs to test
everything and doing it all by yourself. Maybe I shouldn't bother you and just
wait until you get it done.
But I would have thought you would want to clear up any little problems before
putting out a new set of headers. And it might make a nice diversion from all the
other work you've got going on. Sort of give you something easy to do.
I'll shut up now and let you go back to what you were doing.
Have you stopped for a meal lately?
Sorry, but not. I have tried everything and always works except when there is a button outisde the tab pages. In this case, it enters in an endless loop sending WM_SETCURSOR messages. I have asked for help to Dominic, that knows much more than I about Windows common controls, but I guess he is even more busy than I with Phoenix 3.
Dominic has given me a detailed explanation of the problem and two soloutions. The quickest one is to add in the AdTab method of CWindow.inc the following line
dwExStyle = dwExStyle OR %WS_EX_CONTROLPARENT
after the line
IF BITS(LONG, dwExStyle) = -1 THEN dwExStyle = 0
Therefore, the AddTab method will become:
' =====================================================================================
' Adds a tab control to the window.
' =====================================================================================
#IF %DEF(%UNICODE)
METHOD AddTab (BYVAL hParent AS DWORD, BYVAL cID AS LONG, BYVAL strTitle AS WSTRING, _
BYVAL x AS LONG, BYVAL y AS LONG, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG, _
OPTIONAL BYVAL dwStyle AS DWORD, BYVAL dwExStyle AS DWORD, BYVAL pWndProc AS DWORD, BYVAL bNoScale AS LONG) AS DWORD
#ELSE
METHOD AddTab (BYVAL hParent AS DWORD, BYVAL cID AS LONG, BYVAL strTitle AS STRING, _
BYVAL x AS LONG, BYVAL y AS LONG, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG, _
OPTIONAL BYVAL dwStyle AS DWORD, BYVAL dwExStyle AS DWORD, BYVAL pWndProc AS DWORD, BYVAL bNoScale AS LONG) AS DWORD
#ENDIF
LOCAL hCtl AS DWORD
IF dwStyle = 0 OR BITS(LONG, dwStyle) = -1 THEN dwStyle = %WS_VISIBLE OR %WS_GROUP OR %WS_TABSTOP OR %WS_CLIPCHILDREN OR %WS_CLIPSIBLINGS OR %TCS_TABS OR %TCS_SINGLELINE OR %TCS_RAGGEDRIGHT
IF BITS(LONG, dwExStyle) = -1 THEN dwExStyle = 0
dwExStyle = dwExStyle OR %WS_EX_CONTROLPARENT
' // Make sure that the control has the WS_CHILD style
dwStyle = dwStyle OR %WS_CHILD
hCtl = ME.AddControl ("SysTabControl32", hParent, cID, strTitle, x, y, nWidth, nHeight, dwStyle, dwExStyle, %NULL, pWndProc, bNoScale)
IF hCtl = %NULL THEN EXIT METHOD
SendMessage hCtl, %WM_SETFONT, m_hFont, %TRUE
METHOD = hCtl
END METHOD
' =====================================================================================
Thanks. It works.
Now I can put my buttons back where they belong.
Just curious. What was the other method?
The other method is to make the tab pages children of the main wndow instead of the tab control, but this implies to redesign several things.
I designed CWindow to ease SDK programming when coding by hand, not as an OOP-like alternative to the existing Visual designers. I needed it to test that my headers and wrappers worked both as ansi or unicode and High DPI, and was also useful for testing features such classes and dead code removal during the beta testing of PB 10/PBCC 6. It can be used both to build a full GUI or use only some of its methods to ease the embedding of some controls, such I have done recently in the PB forum to embed OCXs or the WebBrowser control in a DDT application.
I leave visual designers to experts like Dominic or Paul and use CWindow to experiment new things without having to wait until these tools are ready. This doesn't mean that CWindow is useless, but most users are going to design his GUIs with a visual designer, not by hand. Anyway, a complex tool like the CSED editor has been written entirely using CWindow, so it means that is powerful.
José,
Ok, I'll take the easy way out.
I was just making another GUI front-end for the Code Formatter.
I had already taken the Phoenix GUI version and converted to DDT. And coded the tab pages
the same way that PB's Tabcontrol sample program did. Simple copy/paste and minor
changes for the different syntax.
Then I decided to try your CWindow routines. Did a copy/paste of the DDT code and minor
changes to the different syntax. And it worked without a problem until I added the buttons.
Minor changes or new controls I can add without any problem. If I ever do a major reworking
of the GUI then I can always use PBForms to lay out the controls and just copy/paste the
new stuff. No problems.
Thanks for all your work.
And
Dominic,
Thanks to you for your help.
Thats why i like the new Firefly 3.5 - its based on CWindows and as a result the results are at top of what we can expect from any VD.
Let's see how Phoenix 3 will be able to top that.
Personally i hope that CWindows will get a new standard for VD in PB. This would mean that all PB Dialogs will be dpi-aware.
Quote
Thats why i like the new Firefly 3.5 - its based on CWindows and as a result the results are at top of what we can expect from any VD.
Let's see how Phoenix 3 will be able to top that.
Personally i hope that CWindows will get a new standard for VD in PB. This would mean that all PB Dialogs will be dpi-aware.
You lost me.
Dialogs in PB would be high DPI-aware if you use dialog units to create them and add the
relevant manifest. You don't need CWindow or its derivatives for that.
The same goes for Phoenix 2.0 except that either pixels(resolution independence set)
or dialog units can be used.
He lost me too.
It will be years before I build anything that high DPI-aware ( not sure what it is ).
I'm still using crt-monitors.
FF is still building tab screens that same way that it did back in v1 ( right ? ).
Not doing the design right on the tab page. You have to create a whole new dialog/form
to do the design on and then show/hide them according to what you want to see.
A step above PBForms ( maybe ) but PB can do the design right on the tab page itself.
No extra dialog/form need be created. And this capability has been there since v9.
Frankly I haven't seen any FF v3.5 code. The test version won't let the user see the compilable
code.
And it is no problem going from straight PB code to Phoenix to CWindow and back.
Just minor differences in the syntax.
Me too :)
I always have stated that it was designed to ease SDK programming when coding by hand. If certain parts can be useful for a visual designer, this is an added bonus.
Quote
Dialogs in PB would be high DPI-aware if you use dialog units to create them and add the
relevant manifest. You don't need CWindow or its derivatives for that.
Indeed. DDT dialogs have however a couple of small problems caused by rounding since they use longs instead of singles.
Quote
FF is still building tab screens that same way that it did back in v1 ( right ? ).
Of course. A method like InsertTabPage is useful when coding by hand, but how are you going to use it in a visual designer? Same for classes such CAfxImageList. In a visual designer you expect to do it by drag and drop or with a helper dialog.
All this comes for lack of understanding of the purposes of my code and also of the problems involved with High DPI.
BTW I have just added two changes: to CWindow I have added properties to allow to set the class name to other than the default; otherwise, you couldn't use this class to build GUIs in DLLs if they where going to be used by a program build with CWindow. The other is a new function added to Windows.inc:
' ========================================================================================
' Retrieve the value of the UseDpiScaling setting (Vista/Windows 7).
' ========================================================================================
FUNCTION AfxGetUseDpiScaling () AS LONG
LOCAL hr AS LONG
LOCAL hKey AS DWORD
LOCAL wszBuff AS WSTRINGZ * 256
LOCAL dwType AS DWORD
LOCAL cbData AS DWORD
IF RegOpenKeyExW(%HKEY_CURRENT_USER, "Software\Microsoft\Windows\DWM", 0, %KEY_QUERY_VALUE, hKey) = %ERROR_SUCCESS THEN
IF hKey THEN
cbData = SIZEOF(wszBuff)
hr = RegQueryValueExW(hKey, "UseDpiScaling", 0, dwType, wszBuff, cbData)
RegCloseKey hKey
IF hr = %ERROR_SUCCESS THEN
wszBuff = EXTRACT$(wszBuff, CHR$(0))
' // Extracts DWORD from string
FUNCTION = CVDWD(wszBuff)
END IF
END IF
END IF
END FUNCTION
' ========================================================================================
If it returns false, you don't have to do scaling even if the DPI is different to 96. This happens when the "Use Windows XP Style DPI Scaling" setting in Vista/Windows 7 is checked.
I wish people will try to learn programing instead of receiving replies like "I don't want lo learn that. I buy tools to not have to learn. I expect that they do all the work for me."
I will post them soon after testing. I hate to post a new version five minutes later just because I have missed some small detail. At this moment, you don't need them unless you want to build a GUI in a DLL that is going to be used by a CWindows application.
FireFly is by no means perfect or the be-all-end-all tool for PB programming. It does what it does and does it pretty well. So what that Tab Controls are created using independent dialogs - it is logical and easy to implement for the user. It is easier than hand coding it and has worked very well for many years. Maybe the Visual Basic approach is easier where you click on the tab and draw controls directly to the embedded dialog but that's not the route I chose because it did not model the SDK approach very well and at the time added a degree of complexity to the FireFly designer itself that I did not want to tackle.
I am in the process of making FireFly and programs it creates High-DPI aware. It is through the use of Jose's cWindow class and his extensive guidance and help that is making this possible. Once I tackle that hurdle then I will try to get the unicode compatibility implemented. I don't program half as much these days as I used to so it takes me longer to get these types of things done. At one point I was programming 6 or 7 hours a day every day...these days, it's lucky I do that each week. Funny how life changes and your passions for things change.
I'm looking forward to seeing Dominic's new Phoenix and every new PB product and 3rd party product. For me, programming and providing FireFly as a visual design tool is not about being the best choice to the detriment of anyone else, or about making the most money, or having the most number of customers, or as some type of ego boost. In the long run, FireFly is just a very small piece of software in the PB universe. I have no desire or motivation to push FireFly through negative advertising of any other competitor's product whether that be Dominic, Edwin, Chris Boss, or PB Forms itself. Everyone has their own style of promoting their software and I learned a couple of years ago that using certain words or phrases certainly rubs people the wrong way. Although done with no intentional malice, it certainly changed my relationship with persons I admire and respect. Since then, programming has lost its lustre. So, I don't engage in debates about SDK, DDT, EZGUI, Phoenix, etc anymore. When people email me asking me to "give me a sales pitch as to why I should choose FireFly over XXXXXX", I simply tell them to read the material on the website and download the demo and try it for themselves.
To be honest, these days I mostly enjoy dealing with customers in the FireFly support forums and helping them use the tool effectively. Learning new approaches to programming and seeing what the Jose's and Dominic's of the world are doing with low level COM is very inspiring.
Paul Squires,
I meant nothing against you or FF. I was very happy to use the method of creating a form/dialog
to create the tab pages. And after I finally got it thru my head what I needed to do to switch
tab pages under program control, things went well.
I only found out about PB's new way of creating tab pages when I tried to help someone on the
PB forums. I did think that it might have been fairly simple to do with a visual designer by drawing
on the real tab ( or at least something of that size ) and creating a small bit of code to do the
creation on the real tab page at run time.
For the past several years all my programming has been small programs for personal use.
I've made due with PB Forms and only occasionally used FF or Phoenix. At times I wish I had a
use for FF v3.5 but just can't justify it.
I didn't mean anything negative by my remarks.
Hey Paul, no offense taken my friend. None at all. It's all good. :)
Quotea visual design tool is not about being the best choice to the detriment of anyone else, or about making the most money, or having the most number of customers, or as some type of ego boost
Well said !
In my own case I have found that my own EZGUI is not for everyone.
When a potential customer emails me I find it important to ask them questions about what they are trying to accomplish and what tools they are familiar with so I can determine whether they are well suited to my own product or someone elses. I have at times strongly suggested to some that for example FireFly may be better suited to their goals and style of programming. rather than my own tools.
Now of course comparisons between products is necessary at times, simply for the sake of defining ones potential market better, but this does not make one product better than another for all people.
In my own case I have found that there seems to be specific mindset to those of my customers who are most productive with my software. I really don't want customers who buy my software, only to shelve it and not be happy with it. That serves little purpose. They waste their money and I don't have a customer who will continue to support my business in the future.
For example I find that it is most difficult for my software to please those who came from a Visual Basic background. Definitely not well suited to using EZGUI ( a few might be). If a potential customer even mentions Visual Basic, I am more likely to kindly push them towards FireFly. Paul has a done an excellent job of the integrated environment (visual design and code editor together) and also he supports ActiveX controls.
On my forums I recently added a topic of comparing FireFly and EZGUI and in good conscience I had to preface the discussion with a nice plug for FireFly and some reasons why someone may prefer it over my software and even a link back to his web site. The comparisons I make on my forum are simply to differentiate my tool from Pauls so those who do buy mine are doing so because they see specific benefits to them personally by using it.
Powerbasic is actually a strange development tool in that their are so many different ways one can use it. There are the DDT users, SDK coders and EZGUI users. Even among SDK coders, there are significantly different styles of coding. There are those who like to impliment as much OOP as possible and those (like me) who tend stay far away from OOP.
The background of each PowerBasic user is also vital in determining which route they may take when using PowerBasic. Did they come from a DOS basic background, from a Visual basic (not dot.net) background, from a Visual Basic (dot.net) or C# background ? Are they moving from the console compiler to the Windows compiler ? All of this determines which development tool will best suit their needs and mindset.
Now in my case, strangely enough, some of my best and most productive customers come from a DOS background and started developing GUI apps using my software. Some of the least satisfied came from a Visual Basic background. Now each group is not all inclusive, since some VBers like and use my software, but I do find trends where a specific group or mindset do better or less better with my tools.
I really think the key is to find out which types of programmers do best with ones tools and to reach out to them. The worse thing would be to have people try to push each 3rd party developer to make their tools more like the other guys. I have some past customers who used EZGUI for a time and the switched to FireFly. Rather than for me to try to emulate FireFly more in my software to try to get them to come back to using EZGUI, I find it better to recognize that for their needs and mindset and programming experience, that FireFly is simply the best product for them.
We don't need all the 3rd party tools to be more like each other. Each has their target user base and benefits to those users. Actually the more each 3rd party tool differentiates itself, the better. There is no "one fits all" when it comes to such tools. It would be better that such tools be uniquely different, but more productive for their user base, then to have them merge and be more like each other.
So Paul, keep doing what you are doing. You have a very happy and productive user base so concentrate on pleasing them.
I don't know if some PB users realize this or not, but some times the most difficult to please users of our products are the ones who buy all of the 3rd party development tools (ie. multiple visual designers). We appreciate the support, but when a programmer keeps switching between these tools it is easier to see how one differs from the other and then to harp on those differences trying to push the developers to be more like the other (I have no specific person in mind, but this is a generalization only). While we may appreciate the feedback, too much pressure to make our tool like the other guys, can actually have a negative impact. It can dim the developers vision for his product. You know the old saying "too many cooks spoil the stew". This can happen with software development.