Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

How to create a function

michael_green
Beginner
672 Views
The following code populates a combo box with a list of file names:

case(WM_COMMAND)
...
else if(LOWORD(uParam)==IDC_theme1.and.HIWORD(uParam)==7)then
iret = GetDlgItemText(dlg%hWnd,IDC_theme1,text,len(text))
text = text(1:strlen(text)) !strlen returns length of visible string, excluding nulls
nFiles = 0
bFoundFile = .true.
hFindFile = FindFirstFile(trim(fmis$dbase)//''//trim(text)// &
'*.map'//char(0),WFDfile)
do while(hFindFile/=INVALID_HANDLE_VALUE.and.bFoundFile)
nFiles = nFiles + 1
call filenm(WFDfile%cFileName,themes(nFiles)) !filenm gets raw filename
bFoundFile = FindNextFile(hFindFile,WFDfile)
end do
bret = DlgSet(dlg,IDC_theme1,nFiles)
do i = 1,nFiles
bret = DlgSet(dlg,IDC_theme1,themes(i),i)
end do
TwtDlgProc = 1
return

It works well, but I have two questions. First, what symbolic name should I use for when the user clicks on the dropdown button of the combo box? (I determined 7 by experiment after trying and failing to find the answer in the online help. Where would such information be?)

Second, I would like to use this code many times for different combo boxes so I guess it needs to be changed into a function. I have never done anything like this before, and have no clear idea about how to set up dummy arguments for the combo boxes, nor how to pass real arguments to the function. Please could someone show me how.

With many thanks

Mike
0 Kudos
3 Replies
Jugoslav_Dujic
Valued Contributor II
672 Views
It's CBN_DROPDOWN.

To find a chapter in Platform SDK help, find "Combo boxes Overview" in the help index, and after you open the page, click on "Locate" toolbar button. The chapter opens in "contents" window and there you'll find all you should know about combo boxes, nicely organized. (Note that some entries are duplicated, because there's some Windows CE and CVF documentation as well -- SDK entries usually have an "Overview" page).

I don't see why turning a piece of code into a subroutine is a problem? But the strange thing I see is that you use a mixture of Win32 API and DFLOGM commands; I find it strange that it works. Where is that piece of code located? If it's in a DialogProc, what does Dlg variable mean? You can't have a DialogProc and a TYPE(Dialog) for the same dialog (unless hacks are involved, like my MenuDialog sample).

Further, why do you fill in contents of combo at the moment of CBN_DROPDOWN? -- that could be painfully slow to open if there are many files. You can (re-)fill the contents only when they have to be changed (i.e. on dialog startup, or if you have another control that would cause the combo contents to be refreshed).

...and you should FindClose(hFindFile) at the end of enumeration.

Jugoslav
0 Kudos
michael_green
Beginner
672 Views
Jugoslav,
Thanks for tips about combo boxes and using the help system - I didn't know about "locate".

To answer your questions about my code, well, it is the way it is because I don't really understand what I am doing. I have been exposed to Fortran 90 and CVF for just 4 months with no teacher other than Norman Lawrence's book and this forum. I find the online help so comprehensive it is overwhelming - it tells me all the things I can do without telling me what I need to do.

Anyway, the code I posted is from a DialogProc. Here it is again in a more complete context:

integer(4) function TwtDlgProc(hDlg,message,uParam,lParam)
!DEC$ IF DEFINED(_X86_)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_TwtDlgProc@16' :: TwtDlgProc
!DEC$ ELSE
!DEC$ ATTRIBUTES STDCALL, ALIAS : 'TwtDlgProc' :: TwtDlgProc
!DEC$ ENDIF
use dfwin
use FMISGlobals
use dflogm
implicit none

integer     hDlg        ! window handle of the dialog box
integer     message     ! type of message
integer     uParam      ! message-specific information
integer     lParam
include 'resource.fd'

integer*4	iret,ios,hFindFile,nFiles,i,strlen
logical  	bret,TwtDataOk,bFoundFile

character*12	theme1,theme2,themes(1000),text
character*50	codes1,codes2

type (dialog) dlg
type (t_startupinfo) si
type (t_process_information) pi
type (t_win32_find_data) WFDfile

character*6		errcode

dlg.hwnd = hDlg

select case(message)
	case(WM_INITDIALOG)
...
	case(WM_COMMAND)
...
		else if(LOWORD(uParam)==IDC_theme1.and.HIWORD(uParam)==CBN_DROPDOWN)then
			iret = GetDlgItemText(dlg%hWnd,IDC_theme1,text,len(text))
			text = text(1:strlen(text))
			nFiles = 0
			bFoundFile = .true.
			hFindFile = FindFirstFile(trim(fmis$dbase)//''//trim(text)// &
				'*.map'//char(0),WFDfile)
			do while(hFindFile/=INVALID_HANDLE_VALUE.and.bFoundFile)
				nFiles = nFiles + 1
				call filenm(WFDfile%cFileName,themes(nFiles))
				bFoundFile = FindNextFile(hFindFile,WFDfile)
			end do
			bret = DlgSet(dlg,IDC_theme1,nFiles)
			do i = 1,nFiles
				bret = DlgSet(dlg,IDC_theme1,themes(i),i)
			end do
			TwtDlgProc = 1
			return



I guess the crucial bit that makes it work is the statement dlg.hwnd = hDlg, and like many of the other things I do, I do it because it works. What's the correct way to do this?

I fill the contents of the combo at dropdown because it is not until then that the program knows what they will be. I am allowing the user the fill in characters to the edit part of the combo in order to limit the number of file names returned. There could be up to a 1000 file names and I don't want to populate the combo with that many at dialog initiation time, whereas with one or two characters typed in, the list will drop back to 20 or 30. Is there a better way to do this?

Many thanks again for all your help,

Mike
0 Kudos
Jugoslav_Dujic
Valued Contributor II
672 Views
I am allowing the user the fill in characters to the edit part of the combo in order to limit the number of file names returned. There could be up to a 1000 file names and I don't want to populate the combo with that many at dialog initiation time, whereas with one or two characters typed in, the list will drop back to 20 or 30. Is there a better way to do this?

Now that you say it, yes, your technique makes sense -- didn't think about it before. Basically, you're reinventing the wheel, as the standard File Open dialog on Win2000 and newer has more or less the same functionality (items in dropdown part of the combo change as you type file name).

I guess the crucial bit that makes it work is the statement dlg.hwnd = hDlg, and like many of the other things I do, I do it because it works. What's the correct way to do this?

In principle, you use either DFLOGM's DlgInit/DlgModal/DlgSetSub, or Win32 DialogBox/DialogProc. In addition, you can tweak some Win32 APIs on top of DFLOGM, but the reverse is not true. OK, you managed to do it :-) -- but it will work only in few cases, as your Dlg variable is only half-valid (it contains also a list of controls within the dialog and their contents).

In your case, you can't use DFLOGM as it doesn't support equivalent of CBN_DROPDOWN for DlgSetSub. So, the "correct" solution is to use native APIs to fill in the combo (to get a quick scan, use "Locate" button as before, then find "Combo box reference"/"Combo box messages" page):
iret = SendDlgItemMessage(hDlg, IDC_THEME1, CB_RESETCONTENT, 0, 0)
do i=1,nThemes
   iret = SendDlgItemMessage(hDlg, IDC_THEME1, CB_ADDSTRING, 0, LOC(themes(i)))
end do
See also CB_DIR message and DlgDirListComboBox routine (I didn't know about them either) -- might be interesting for your use.

Jugoslav
0 Kudos
Reply