- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am familiar with the Listbox and have used it successfully many times. Now, I am attempting to use the LISTVIEW control in a dialog box. I have successfully loaded data into the control, but now I want the application to call a subroutine when an a row is clicked in the LISTVIEW control. I have used the "dlgsetsub" funtion to define which callback subroutine to call, but nothing happens when a row in the LISTVIEW control is clicked. Should this work or should I be doing something different. Any help that you can provide would be greatly appreciated.
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Unfortunately, no, ListView is not supported by DFLOGM, so you'll have to cope with pure API handling. This is somewhat less elegant (but more powerful) than Dlg* family of routines.
Here's a code snippet from an actual application which handles the dialog whose screenshot is in the attachment.
(There are two similar ListViews, which are shown/hidden depending on tab control state; I snipped the code which handles the second because it's more or less identical).
It is a bit more complicated since it's from an actual app, but hope it would be helpful.
HTH
Jugoslav
Here's a code snippet from an actual application which handles the dialog whose screenshot is in the attachment.
(There are two similar ListViews, which are shown/hidden depending on tab control state; I snipped the code which handles the second because it's more or less identical).
It is a bit more complicated since it's from an actual app, but hope it would be helpful.
!=========================================================
INTEGER(4) FUNCTION ScadaIDDlgProc(hWnd,Msg,wParam,lParam)
!DEC$ATTRIBUTES STDCALL:: ScadaIDDlgProc
USE DFWIN
USE LANGDEP
USE OPCCLIENT
USE COMCTL
USE STRINGS
USE REGISTRY
USE UKS
USE me_com1
IMPLICIT NONE
INCLUDE "Resource.fd"
INTEGER, INTENT(IN):: hWnd, Msg, wParam, lParam
INTEGER:: i, iSt, hIcon, iIcon
INTEGER, SAVE:: hImageList = 0, hList1, hList2
CHARACTER(100):: sID
TYPE(T_LV_ITEM):: Item
TYPE(T_TC_ITEM):: TabItem
TYPE(T_LV_COLUMN):: Column
TYPE(T_NM_LISTVIEW):: LV; POINTER(pLV,LV)
TYPE(T_NMHDR):: Hdr; POINTER(pHdr,Hdr)
INTEGER, PARAMETER:: sColumn(0:4)=(/S_SCADAID, S_DMSID, S_STATUS, S_QUALITY, S_LOCATION/)
INTEGER, PARAMETER:: sMerColumn(0:5)=(/S_SCADAID, S_DMSID, S_VALUE, S_TYPE, &
S_QUALITY, S_LOCATION/)
INTEGER, PARAMETER:: sQuality(1:3)=(/S_GOOD, S_UNCERTAIN, S_BAD/)
INTEGER, PARAMETER:: iColWidth(0:4)=(/60, 60, 40, 40, 312/)
INTEGER, PARAMETER:: iMerColWidth(0:5)=(/60, 60, 60, 40, 40, 252/)
INTEGER, PARAMETER:: idIcon(0:2)=(/IDI_ICON_GOOD, IDI_ICON_UNCERTAIN, IDI_ICON_BAD/)
!This is the function for sorting elements by columns
INTERFACE
INTEGER FUNCTION ListSortFunc(i1,i2,i3)
!DEC$ATTRIBUTES STDCALL:: ListSortFunc
INTEGER:: i1,i2,i3
END FUNCTION ListSortFunc
END INTERFACE
SELECT CASE(MSG)
CASE (WM_INITDIALOG)
hList1 = GetDlgItem(hWnd, IDC_LIST1)
hList2 = GetDlgItem(hWnd, IDC_LIST2)
TabItem%mask = TCIF_TEXT
TabItem%pszText = LOC(sID)
!.C. is a character function which loads a string
!from a dll string table. Use normal strings instead.
sID = .C.S_SWITCHGEAR
iSt = SendMessage(GetDlgItem(hWnd, IDC_TAB1), TCM_INSERTITEM, 0, LOC(TabItem))
sID = .C.S_MEASUREMENTS
iSt = SendMessage(GetDlgItem(hWnd, IDC_TAB1), TCM_INSERTITEM, 1, LOC(TabItem))
iSt = ShowWindow(hList1, SW_SHOW)
iSt = ShowWindow(hList2, SW_HIDE)
iSt = ShowWindow(GetDlgItem(hWnd,IDC_STATIC1), SW_SHOW)
iSt = ShowWindow(GetDlgItem(hWnd,IDC_STATIC2), SW_HIDE)
iSt = SendMessage(GetDlgItem(hWnd, IDOK), BM_SETIMAGE, IMAGE_ICON, hicoOK)
!Setting up the header control
DO i=0,4
Column%mask = LVCF_FMT + LVCF_ORDER + LVCF_SUBITEM + LVCF_TEXT + LVCF_WIDTH
Column%fmt = LVCFMT_LEFT
Column%cx = iColWidth(i)
sID = .C.sColumn(i)
Column%pszText = LOC(sID)
Column%cchTextMax = 0
Column%iSubItem = i
Column%iImage = 0
Column%iOrder = i
iSt = SendMessage(hList1, LVM_INSERTCOLUMN, i, LOC(Column))
END DO
DO i=0,5
sID = .C.sMerColumn(i)
Column%cx = iMerColWidth(i)
Column%iSubItem = i
Column%iOrder = i
iSt = SendMessage(hList2, LVM_INSERTCOLUMN,
i, LOC(Column))
END DO
DO i=1,iBrKom
IF (iRConPr(i).NE.0) THEN
iIcon = 0
Item%mask = LVIF_TEXT + LVIF_IMAGE + LVIF_PARAM
Item%iItem = 0
Item%state = 0
Item%statemask = 0
Item%cchTextMax = 0
Item%iImage = -1
!lParam is optional; here it is used
!to associate data with each row, in
!order to enable sorting
Item%lParam = i
Item%iSubItem = 0
CALL GetScadaID(i, 1, sID)
IF (LEN_TRIM(sID).LE.1) iIcon = 1
sID = TRIM(sID)//CHAR(0)
Item%pszText = LOC(sID)
iSt = SendMessage(hList1, LVM_INSERTITEM, 0, LOC(Item))
Item%mask = LVIF_TEXT
Item%iSubItem = 1
sID = STRING(iSifPr(i),9)
sID = TRIM(sID)//CHAR(0)
iSt = SendMessage(hList1, LVM_SETITEM, 0, LOC(Item))
Item%iSubItem = 2
sID = STRING(iStPr(i),1)
sID = TRIM(sID)//CHAR(0)
iSt = SendMessage(hList1, LVM_SETITEM, 0, LOC(Item))
Item%iSubItem = 3
sID = .C.sQuality(iRConPr(i))
Item%iImage = iRConPr(i)-1
iSt = SendMessage(hList1, LVM_SETITEM, 0, LOC(Item))
Item%iSubItem = 4
CALL GetSwitchName(iSifPr(i), sID, .TRUE., iSt)
IF (LEN_TRIM(sID).LE.1) iIcon = 2
sID = TRIM(sID)//CHAR(0)
iSt = SendMessage(hList1, LVM_SETITEM, 0, LOC(Item))
IF (iIcon.NE.0) THEN
Item%mask = LVIF_IMAGE
Item%iSubItem = 0
Item%iImage = iIcon
iSt = SendMessage(hList1, LVM_SETITEM, 0, LOC(Item))
END IF
END IF
END DO
!
!Adding icons to the list
hImageList = ImageList_Create(16, 16, ILC_COLOR+ILC_MASK, 6, 2)
DO i=0,2
hIcon = LoadImageA(hInst, idIcon(i), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR )
iSt = ImageList_ReplaceIcon(hImageList, -1, hIcon)
END DO
iSt = SendMessage(hList1, LVM_SETIMAGELIST, LVSIL_SMALL, hImageList)
iSt = SendMessage(hList2, LVM_SETIMAGELIST, LVSIL_SMALL, hImageList)
ScadaIDDlgProc = .FALSE.
CASE (WM_COMMAND)
IF (LOWORD(wParam).EQ.IDOK) THEN
iSt = EndDialog(hWnd, IDOK)
END IF
ScadaIDDlgProc = .TRUE.
CASE (WM_NOTIFY)
pHdr = lParam
IF (wParam.EQ.IDC_LIST1) THEN
IF (hdr%code.EQ.LVN_COLUMNCLICK) THEN
pLV = lParam
iSt = SendMessage(hList1, LVM_SORTITEMS, LV%iSubItem+1, LOC(ListSortFunc))
END IF
ELSE IF (wParam.EQ.IDC_LIST2) THEN
IF (hdr%code.EQ.LVN_COLUMNCLICK) THEN
pLV = lParam
iSt = SendMessage(hList2, LVM_SORTITEMS, -LV%iSubItem-1, LOC(ListSortFunc))
END IF
ELSE IF (wParam.EQ.IDC_TAB1) THEN
IF (hdr%code.EQ.TCN_SELCHANGE) THEN
iSt = SendMessage(GetDlgItem(hWnd, IDC_TAB1), TCM_GETCURSEL, 0, 0)
IF (iSt.EQ.0) THEN
iSt = ShowWindow(hList1, SW_SHOW)
iSt = ShowWi
ndow(hList2, SW_HIDE)
iSt = ShowWindow(GetDlgItem(hWnd,IDC_STATIC1), SW_SHOW)
iSt = ShowWindow(GetDlgItem(hWnd,IDC_STATIC2), SW_HIDE)
ELSE
iSt = ShowWindow(hList1, SW_HIDE)
iSt = ShowWindow(hList2, SW_SHOW)
iSt = ShowWindow(GetDlgItem(hWnd,IDC_STATIC1), SW_HIDE)
iSt = ShowWindow(GetDlgItem(hWnd,IDC_STATIC2), SW_SHOW)
END IF
END IF
END IF
CASE DEFAULT
ScadaIDDlgProc = .FALSE.
END SELECT
END FUNCTION ScadaIDDlgProc
!================================
INTEGER FUNCTION ListSortFunc(i1,i2,iColumn)
!DEC$ATTRIBUTES STDCALL:: ListSortFunc
USE me_com1
USE UKS
IMPLICIT NONE
INTEGER, INTENT(IN):: i1,i2,iColumn
CHARACTER(100):: sID1, sID2
INTEGER:: iSt
IF (iColumn.GT.0) THEN
!Prekidaci
SELECT CASE (iColumn)
CASE(1)
CALL GetScadaID(i1, 1, sID1)
CALL GetScadaID(i2, 1, sID2)
IF (sID1.EQ.sID2) THEN
ListSortFunc = 0
ELSE IF (sID1.GT.sID2) THEN
ListSortFunc = 1
ELSE
ListSortFunc = -1
END IF
CASE(2)
ListSortFunc = iSifPr(i1)-iSifPr(i2)
!Snipped the restHTH
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the input. I was hoping there may be an easy way to use a LISTVIEW control without getting to deep into API handling. Any thoughts on how to handle a LISTVIEW while still using DFLOGM would be appreciated.
Joe
Joe
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, there are two ways, none of them particularly attractive:
- The "pure" way is to use ActiveX wrapper for ListView control (it is located in comctl32.ocx). All that ActiveX stuff is Greek to me so you'll have to rely on samples, MSDN documentation and pelhaps help from other Forum participants.
- The other way is to tweak DFLOGM.f90 (my favourite sport) to roll your own ListView (or, perhaps, general "unknown control") support, i.e. develop the structure, handle WM_COMMAND and WM_NOTIFY etc.
Jugoslav
- The "pure" way is to use ActiveX wrapper for ListView control (it is located in comctl32.ocx). All that ActiveX stuff is Greek to me so you'll have to rely on samples, MSDN documentation and pelhaps help from other Forum participants.
- The other way is to tweak DFLOGM.f90 (my favourite sport) to roll your own ListView (or, perhaps, general "unknown control") support, i.e. develop the structure, handle WM_COMMAND and WM_NOTIFY etc.
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi there,
I created a ListView Control and I am able toinsert new columns, items etc. The difference is the implemantation of the code. You insert new data by messages, I set them when I create the dialog within the MainDialog Callback Routine.
Now I tried to implement two features: Sorting the columns and edit the label. But where do I "intercept" the WM_NOTIFY Message? Do I have to rewrite the code?
Code:
l = DlgInit(IDD_DIALOG_Main, dlgMain)
l = DlgSetSub(dlgMain, IDD_DIALOG_Main, MainInit)
...
l = DlgModeless(dlgMain)
do while( GetMessage (mesg, NULL, 0, 0) )
if (DlgIsDlgMessage(mesg) .EQV. .FALSE. ) then
lret = TranslateMessage( mesg )
ret = DispatchMessage( mesg )
end if
end do
...
! *********************************************************************
SUBROUTINE MainInit( dlg, id, callbacktype )
! *********************************************************************
use...
ListHwnd = GetDlgItem(dlg.hwnd,IDC_LIST_Chemie)
l = SendMessage(ListHwnd,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FULLROWSELECT)
LVColumn.mask = LVCF_FMT+LVCF_ORDER+LVCF_SUBITEM+LVCF_TEXT+LVCF_WIDTH
LVColumn.cchTextMax = 0
LVColumn.iImage = 0
LVColumn.fmt = LVCFMT_RIGHT
...
l = SendMessage(ListHwnd, LVM_INSERTCOLUMN, 0, LOC(LVColumn))
LVColumn.fmt=LVCFMT_LEFT
...
l = SendMessage(ListHwnd, LVM_INSERTCOLUMN, 1, LOC(LVColumn))
...
end subroutin- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Basically, you can't :-(. Either you must tweak DFLOGM.f90 code or insert an ugly
In the meantime, I developed ListView support in <XFT library with kind help of Mike Gaitens -- check out the LVTest sample.
I hope the code and documentation are clear enough.
Jugoslav
if (Msg%message.EQ.WM_NOTIFY .AND. Msg%hWnd.EQ.Dlg%hWnd .AND. &
(the NMHDR%idFrom is listview control)) then
!do something
else
TranslateMessage
DispatchMessage
end if
In the meantime, I developed ListView support in <XFT library with kind help of Mike Gaitens -- check out the LVTest sample.
I hope the code and documentation are clear enough.
Jugoslav
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page