Page 2 of 2
Re: RC to PRG generator
Posted: Mon Feb 12, 2024 11:12 pm
by Giovany Vecchi
Antonio.
I've already done some tests and I couldn't identify the GoupBox control.
The control is assigned to the BUTTON type.
I needed a way to identify the BS_GROUPBOX too.
Code: Select all | Expand
CONTROL "Guias Anteriores", 1101, "Button", BS_GROUPBOX, 2, 13, 135, 22
CONTROL "Atualizar para", 1102, "Button", BS_GROUPBOX, 2, 35, 135, 22
Re: RC to PRG generator
Posted: Mon Feb 12, 2024 11:27 pm
by TimStone
Antonio,
One small thought. You are using oDlg each time. I realize it is LOCAL and that should be OK, but over the years, I find in my experience, sometimes I still have issues arise. In my case, I often give the dialogs unique names, especially if I will have multiple ones on the same screen. For example, when using folders, I have a master dialog, and each folder has its own dialog.
So, you may wish to include an option to assign a name for the dialog that will be used by the program when it creates each control.
Tim
Re: RC to PRG generator
Posted: Tue Feb 13, 2024 2:59 am
by Marcelo Via Giglio
Hola Antonio,
Interesting work, I think it can be the start to another aproach to start a visual form builder, rc and prg source generator
Saludos cordiales
Marcelo Via
Re: RC to PRG generator
Posted: Tue Feb 13, 2024 8:19 am
by Antonio Linares
Enhanced version:
Code: Select all | Expand
#include "FiveWin.ch"
#define GWL_STYLE -16
static nButtons := 0, nLbxs := 0, nGets := 0, nTrackBars := 0, nXBrowses := 0, nMeterExs := 0
static nGroups := 0, nRadios := 0
function Main()
local oDlg
TMeterEx():Register()
TXBrowse():Register()
DEFINE DIALOG oDlg RESOURCE "test"
ACTIVATE DIALOG oDlg CENTERED ;
ON RIGHT CLICK WritePrg( oDlg )
return nil
function WritePrg( oDlg )
local cPrg := "", n, cVars := ""
EnumChildWindows( oDlg:hWnd, { | hCtrl | cPrg += GenCode( hCtrl ) } )
if nButtons > 0
cVars += "local "
for n = 1 to nButtons
cVars += If( n > 1, ", ", "" ) + "oBtn" + AllTrim( Str( n ) )
next
cVars += CRLF
endif
if nLbxs > 0
cVars += "local "
for n = 1 to nLbxs
cVars += If( n > 1, ", ", "" ) + "oLbx" + AllTrim( Str( n ) )
next
cVars += CRLF
endif
if nGets > 0
cVars += "local "
for n = 1 to nGets
cVars += If( n > 1, ", ", "" ) + "oGet" + AllTrim( Str( n ) )
next
cVars += CRLF
endif
if nTrackBars > 0
cVars += "local "
for n = 1 to nTrackBars
cVars += If( n > 1, ", ", "" ) + "oTrb" + AllTrim( Str( n ) )
next
cVars += CRLF
endif
if nXBrowses > 0
cVars += "local "
for n = 1 to nXBrowses
cVars += If( n > 1, ", ", "" ) + "oXbrw" + AllTrim( Str( n ) )
next
cVars += CRLF
endif
if nMeterExs > 0
cVars += "local "
for n = 1 to nMeterExs
cVars += If( n > 1, ", ", "" ) + "oMtr" + AllTrim( Str( n ) )
next
cVars += CRLF
endif
if nGroups > 0
cVars += "local "
for n = 1 to nGroups
cVars += If( n > 1, ", ", "" ) + "oGrp" + AllTrim( Str( n ) )
next
cVars += CRLF
endif
if nRadios > 0
cVars += "local "
for n = 1 to nGroups
cVars += If( n > 1, ", ", "" ) + "oRad" + AllTrim( Str( n ) )
next
cVars += CRLF
endif
FW_memoEdit( cVars + CRLF + 'DEFINE DIALOG oDlg RESOURCE "' + oDlg:cResName + '"' + ;
CRLF + CRLF + cPrg + "ACTIVATE DIALOG oDlg CENTERED" )
return nil
function GenCode( hCtrl )
local cCode := "REDEFINE "
local cClass := Upper( GetClassName( hCtrl ) )
static hPrevCtrl
do case
case cClass == "BUTTON"
if nAnd( GetWindowLong( hCtrl, GWL_STYLE ), BS_AUTORADIOBUTTON ) == BS_AUTORADIOBUTTON
cCode += "RADIO oRad" + AllTrim( Str( ++nRadios ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CLICK ''" + " // " + LTrim( GetWindowText( hCtrl ) )
elseif nAnd( GetWindowLong( hCtrl, GWL_STYLE ), BS_GROUPBOX ) == BS_GROUPBOX
cCode += "GROUP oGrp" + AllTrim( Str( ++nGroups ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"+ " // " + LTrim( GetWindowText( hCtrl ) )
else
cCode += "BUTTON oBtn" + AllTrim( Str( ++nButtons ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ACTION ''"
endif
case cClass == "EDIT"
cCode += "GET oGet" + AllTrim( Str( ++nGets ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg" + If( lAnd( GetWindowLong( hCtrl, GWL_STYLE ), ES_MULTILINE ), " MULTILINE", "" ) + ;
" // " + If( ! Empty( hPrevCtrl ) .and. ;
Upper( GetClassName( hPrevCtrl ) ) == "STATIC", GetWindowText( hPrevCtrl ), "" )
case cClass == "LISTBOX"
cCode += "LISTBOX oLbx" + AllTrim( Str( ++nLbxs ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CHANGE ''"
case cClass == "MSCTLS_TRACKBAR32"
cCode += "TRACKBAR oTrb" + AllTrim( Str( ++nTrackBars ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CHANGE ''"
case cClass == "TXBROWSE"
cCode += "XBROWSE oBrw" + AllTrim( Str( ++nXBrowses ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"
case cClass == "STATIC"
cCode = ""
case cClass == "TMETEREX"
cCode += "METEREX oMtr" + AllTrim( Str( ++nMeterExs ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"
otherwise
MsgInfo( cClass )
endcase
hPrevCtrl = hCtrl
return cCode + If( ! Empty( cCode ), CRLF + CRLF, "" )
Re: RC to PRG generator
Posted: Tue Feb 13, 2024 9:11 am
by Antonio Linares
Simplifying the code:
Code: Select all | Expand
#include "FiveWin.ch"
#define GWL_STYLE -16
static hVars := { "oBtn" => 0, "oLbx" => 0, "oGet" => 0, "oTbr" => 0,;
"oBrw" => 0, "oMtr" => 0, "oGrp" => 0, "oRad" => 0 }
function Main()
local oDlg
TMeterEx():Register()
TXBrowse():Register()
DEFINE DIALOG oDlg RESOURCE "test"
ACTIVATE DIALOG oDlg CENTERED ;
ON RIGHT CLICK WritePrg( oDlg )
return nil
function WritePrg( oDlg )
local cPrg := "", n, cVars := "", cKey
EnumChildWindows( oDlg:hWnd, { | hCtrl | cPrg += GenCode( hCtrl ) } )
for each cKey in hb_HKeys( hVars )
if hVars[ cKey ] != 0
cVars += "local "
for n = 1 to hVars[ cKey ]
cVars += If( n > 1, ", ", "" ) + cKey + AllTrim( Str( n ) )
next
cVars += CRLF
endif
next
FW_memoEdit( cVars + CRLF + 'DEFINE DIALOG oDlg RESOURCE "' + oDlg:cResName + '"' + ;
CRLF + CRLF + cPrg + "ACTIVATE DIALOG oDlg CENTERED" )
return nil
function GenCode( hCtrl )
local cCode := "REDEFINE "
local cClass := Upper( GetClassName( hCtrl ) )
static hPrevCtrl
do case
case cClass == "BUTTON"
if nAnd( GetWindowLong( hCtrl, GWL_STYLE ), BS_AUTORADIOBUTTON ) == BS_AUTORADIOBUTTON
cCode += "RADIO oRad" + AllTrim( Str( ++hVars[ "oRad" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CLICK ''" + " // " + LTrim( GetWindowText( hCtrl ) )
elseif nAnd( GetWindowLong( hCtrl, GWL_STYLE ), BS_GROUPBOX ) == BS_GROUPBOX
cCode += "GROUP oGrp" + AllTrim( Str( ++hVars[ "oGrp" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"+ " // " + LTrim( GetWindowText( hCtrl ) )
else
cCode += "BUTTON oBtn" + AllTrim( Str( ++hVars[ "oBtn" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ACTION ''"
endif
case cClass == "EDIT"
cCode += "GET oGet" + AllTrim( Str( ++hVars[ "oGet" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg" + If( lAnd( GetWindowLong( hCtrl, GWL_STYLE ), ES_MULTILINE ), " MULTILINE", "" ) + ;
" // " + If( ! Empty( hPrevCtrl ) .and. ;
Upper( GetClassName( hPrevCtrl ) ) == "STATIC", GetWindowText( hPrevCtrl ), "" )
case cClass == "LISTBOX"
cCode += "LISTBOX oLbx" + AllTrim( Str( ++hVars[ "oLbx" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CHANGE ''"
case cClass == "MSCTLS_TRACKBAR32"
cCode += "TRACKBAR oTrb" + AllTrim( Str( ++hVars[ "oTrb"] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CHANGE ''"
case cClass == "TXBROWSE"
cCode += "XBROWSE oBrw" + AllTrim( Str( ++hVars[ "oBrw" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"
case cClass == "STATIC"
cCode = ""
case cClass == "TMETEREX"
cCode += "METEREX oMtr" + AllTrim( Str( ++hVars[ "oMtr" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"
otherwise
MsgInfo( cClass )
endcase
hPrevCtrl = hCtrl
return cCode + If( ! Empty( cCode ), CRLF + CRLF, "" )
Re: RC to PRG generator
Posted: Tue Feb 13, 2024 11:20 am
by Antonio Linares
Now we list all the dialogs that are available in the embedded RES inside the EXE and allows you to select one and generate the code for it:
simply rename your RC file as rctoprg.rc and build rctoprg.prg
If you keep your dialogs inside a DLL then replace GetInstance() for LoadLibrary( "yourdll.dll" )
This example and the new C code listed at the bottom will be included in next FWH build.
rctoprg.prg
Code: Select all | Expand
#include "FiveWin.ch"
#define GWL_STYLE -16
#define RT_DIALOG MakeIntResource( 5 )
static hVars := { "oBtn" => 0, "oLbx" => 0, "oGet" => 0, "oTbr" => 0,;
"oBrw" => 0, "oMtr" => 0, "oGrp" => 0, "oRad" => 0 }
function Main()
local oDlg, cDlgName, aDlgNames := {}, oLbx, oGetCode, cCode := Space( 800 ), oDlgNew
TMeterEx():Register()
TXBrowse():Register()
TFolderEx():Register()
EnumResourceNames( GetInstance(), RT_DIALOG, { | cDlgName | AAdd( aDlgNames, cDlgName ), .T. } )
DEFINE DIALOG oDlg TITLE "RC dialogs to PRG" SIZE 720, 500
@ 0, 1.5 SAY "Select a dialog" OF oDlg
@ 1, 1 LISTBOX oLbx VAR cDlgName ITEMS aDlgNames OF oDlg SIZE 100, 200
@ 12, 5 BUTTON "Generate" OF oDlg ACTION oDlgNew := BuildDialog( cDlgName, oGetCode )
@ 12, 16 BUTTON "End" OF oDlg ACTION oDlgNew:End()
@ 1.1, 14 GET oGetCode VAR cCode OF oDlg MULTILINE SIZE 240, 188
ACTIVATE DIALOG oDlg ON INIT oDlg:SetPos( 300, 100 )
return nil
function BuildDialog( cDlgName, oGetCode )
local oDlg
DEFINE DIALOG oDlg RESOURCE ( cDlgName )
ACTIVATE DIALOG oDlg NOWAIT ON INIT ( oDlg:SetPos( 300, 900 ), WritePrg( oDlg, oGetCode ) )
return oDlg
function WritePrg( oDlg, oGetCode )
local cPrg := "", n, cVars := "", cKey
EnumChildWindows( oDlg:hWnd, { | hCtrl | cPrg += GenCode( hCtrl ) } )
for each cKey in hb_HKeys( hVars )
if hVars[ cKey ] != 0
cVars += "local "
for n = 1 to hVars[ cKey ]
cVars += If( n > 1, ", ", "" ) + cKey + AllTrim( Str( n ) )
next
cVars += CRLF
endif
next
oGetCode:SetText( cVars + CRLF + 'DEFINE DIALOG oDlg RESOURCE "' + oDlg:cResName + '"' + ;
CRLF + CRLF + cPrg + "ACTIVATE DIALOG oDlg CENTERED" )
return nil
function GenCode( hCtrl )
local cCode := "REDEFINE "
local cClass := Upper( GetClassName( hCtrl ) )
static hPrevCtrl
do case
case cClass == "BUTTON"
if nAnd( GetWindowLong( hCtrl, GWL_STYLE ), BS_AUTORADIOBUTTON ) == BS_AUTORADIOBUTTON
cCode += "RADIO oRad" + AllTrim( Str( ++hVars[ "oRad" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CLICK ''" + " // " + LTrim( GetWindowText( hCtrl ) )
elseif nAnd( GetWindowLong( hCtrl, GWL_STYLE ), BS_GROUPBOX ) == BS_GROUPBOX
cCode += "GROUP oGrp" + AllTrim( Str( ++hVars[ "oGrp" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"+ " // " + LTrim( GetWindowText( hCtrl ) )
else
cCode += "BUTTON oBtn" + AllTrim( Str( ++hVars[ "oBtn" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ACTION ''"
endif
case cClass == "EDIT"
cCode += "GET oGet" + AllTrim( Str( ++hVars[ "oGet" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg" + If( lAnd( GetWindowLong( hCtrl, GWL_STYLE ), ES_MULTILINE ), " MULTILINE", "" ) + ;
" // " + If( ! Empty( hPrevCtrl ) .and. ;
Upper( GetClassName( hPrevCtrl ) ) == "STATIC", GetWindowText( hPrevCtrl ), "" )
case cClass == "LISTBOX"
cCode += "LISTBOX oLbx" + AllTrim( Str( ++hVars[ "oLbx" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CHANGE ''"
case cClass == "MSCTLS_TRACKBAR32"
cCode += "TRACKBAR oTrb" + AllTrim( Str( ++hVars[ "oTrb"] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg ON CHANGE ''"
case cClass == "TXBROWSE"
cCode += "XBROWSE oBrw" + AllTrim( Str( ++hVars[ "oBrw" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"
case cClass == "STATIC"
cCode = ""
case cClass == "TMETEREX"
cCode += "METEREX oMtr" + AllTrim( Str( ++hVars[ "oMtr" ] ) ) + " ID " + AllTrim( Str( GetDlgCtrlId( hCtrl ) ) ) + ;
" OF oDlg"
otherwise
MsgInfo( cClass )
endcase
hPrevCtrl = hCtrl
return cCode + If( ! Empty( cCode ), CRLF + CRLF, "" )
#pragma BEGINCODE
#include <Windows.h>
#include <hbapi.h>
#include <hbapiitm.h>
//---------------------------------------------------------------------------//
static BOOL CALLBACK EnumResourceNamesCallback( HMODULE hModule, LPSTR lpszType, LPSTR lpszName, LONG_PTR lParam )
{
( void ) hModule;
if( lpszType == RT_DIALOG )
{
PHB_ITEM pStrName = hb_itemPutC( NULL, lpszName );
hb_evalBlock1( ( PHB_ITEM ) lParam, pStrName );
hb_itemRelease( pStrName );
}
return hb_parl( -1 ); // .T. continue enumeration
}
//---------------------------------------------------------------------------//
HB_FUNC( ENUMRESOURCENAMES )
{
#ifndef _WIN64
EnumResourceNames( ( HMODULE ) hb_parnl( 1 ), ( const signed char * ) hb_parnl( 2 ),
( ENUMRESNAMEPROC ) EnumResourceNamesCallback, ( LONG_PTR ) hb_param( 3, HB_IT_BLOCK ) );
#else
EnumResourceNames( ( HMODULE ) hb_parnll( 1 ), ( const signed char * ) hb_parnl( 2 ),
( ENUMRESNAMEPROC ) EnumResourceNamesCallback, ( LONG_PTR ) hb_param( 3, HB_IT_BLOCK ) );
#endif
}
//---------------------------------------------------------------------------//
#pragma ENDCODE
https://github.com/FiveTechSoft/screens ... g?raw=true
Re: RC to PRG generator
Posted: Thu Feb 15, 2024 1:27 pm
by vilian
Where could i find file windows.h ?
Re: RC to PRG generator
Posted: Thu Feb 15, 2024 1:31 pm
by Antonio Linares
vilian wrote:Where could i find file windows.h ?
The C compiler provides it
Re: RC to PRG generator
Posted: Thu Feb 15, 2024 1:54 pm
by vilian
Thank you