News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Inserting a small button inside a Syslistview ccontrol

Started by guga, August 28, 2023, 03:06:10 PM

Previous topic - Next topic

guga

Hi guys

how to embed a button inside a syslistview (that is inside a dialog and now windows form) ?

I found a code but it is in .Net and i couldn´t be able to port it.

https://www.codeproject.com/Articles/9188/Embedding-Controls-in-a-ListView

Since i wasn´t able to port, i then tried to convert a checkbox inside the syslistcontrol onto a normal button, by retrieving the handle of that checkbox, but also returned zero.

So, i have 2 questions....Can this .Net be ported ?

And if not...

How to retrieve the hanndle of a check box existent inside a certain item and subitem os a syslistvioew control existent in a dialogbox ?

I made this o try o retrieve the handle, but it keeps returning zero.

call GetCheckboxHandleInListView D@hList, 1, 3

Proc GetCheckboxHandleInListView:
    Arguments @hList, @RowIndex, @ColumnIndex
    Local @CheckBoxX, @CheckBoxY
    Structure @SubitemRect 24, @SubitemRect.leftDis 0, @SubitemRect.topDis 4, @SubitemRect.rightDis 8, @SubitemRect.bottomDis 12,
                               @SubitemRect.PointXDis 16, @SubitemRect.PointYDis 20
    Uses ecx, edx

    ; Calculate the position of the checkbox within the subitem's rectangle
    ;int checkboxX = itemRect.left + columnIndex * 20; // Adjust as needed
    ;int checkboxY = itemRect.top + (itemRect.bottom - itemRect.top) / 2;

    call ListView_GetSubItemRect D@hList, D@RowIndex, D@ColumnIndex, &LVIR_BOUNDS, D@SubitemRect

    ; Calculate the position of the checkbox within the item's rectangle
    lea ecx D@SubitemRect.PointXDis
    mov eax D@SubitemRect.leftDis | mov D$ecx eax;mov D@CheckBoxX eax
    mov eax D@SubitemRect.bottomDis | sub eax D@SubitemRect.topDis | shr eax 1 | add eax D@SubitemRect.topDis | mov D$ecx+4 eax;mov D@CheckBoxY eax

    ; Get the handle of the child window (checkbox) at the specified position

    call 'USER32.ScreenToClient' D@hList, ecx
    lea ecx D@SubitemRect.PointXDis
    call 'USER32.ChildWindowFromPoint' D@hList, ecx

EndP


Proc ListView_GetSubItemRect:
    Arguments @hwnd, @iItem, @iSubItem, @code, @prc
    Uses ecx, edx

    mov eax D@prc
    mov ecx D@code | mov D$eax+RECT.leftDis ecx
    mov ecx D@iSubItem | mov D$eax+RECT.topDis ecx
    mov D$eax+RECT.rightDis 0
    mov D$eax+RECT.bottomDis 0

    call 'USER32.SendMessageA' D@hwnd, &LVM_GETSUBITEMRECT, D@iItem, D@prc;((D@prc) ? ((((LPRECT)(D@prc))->top = D@iSubItem), (((LPRECT)(D@prc))->left = D@code), (LPARAM)(D@prc)) : (LPARAM)(LPRECT)NULL)

EndP


Is there a way to do it ?  I mean, or directly creating a button isnide a syslistview control (at a speific row and col) or by retrieving the handle of a existent checkbox and then converting it onto a normal button (afterall, a checkbox is nothing but a button)

Btw...what i mean with a small button, is the same as the image below


I wanted to do as the image below. I suceeded to create a checkbox, but i wouuld like to add an extra button at the last column (and perhaps with a label too on the last column)

This buton wil be used to open the opendialog function to load a file and retrieve/fix a path to be displayed in the syslistview control on the item that is missing a path

Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

NoCforMe

Dunno if this'll help, as I've never tried embedding a button in a listview control (I assume that's what you mean when you say "inside a syslistview"?). I have, however, successfully embedded buttons in a listbox, like what you see here. I imagine this might well work with a listview as well.

This was very simple: I just got the screen client coordinates of the location in the listbox where I wanted the button, then sized and positioned a "floating" button accordingly (I made the button a child of the listbox). When I don't want the button to appear, I simply hide it.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Here's the same thing except with an embedded combobox within the listbox:
Assembly language programming should be fun. That's why I do it.

guga

Quote from: NoCforMe on August 28, 2023, 03:25:31 PMDunno if this'll help, as I've never tried embedding a button in a listview control (I assume that's what you mean when you say "inside a syslistview"?). I have, however, successfully embedded buttons in a listbox, like what you see here. I imagine this might well work with a listview as well.

This was very simple: I just got the screen client coordinates of the location in the listbox where I wanted the button, then sized and positioned a "floating" button accordingly (I made the button a child of the listbox). When I don't want the button to appear, I simply disable it.


How you managed to do that small button ?

About the listbos too, pls.

I found one example of a combobox, but uses MFC - https://www.codeproject.com/Articles/5709/Customized-Report-List-Control-With-In-Place-Combo


What i mean with syslistview, is the syslistview32 class and not the regular listbox.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

NoCforMe

Quote from: guga on August 28, 2023, 03:40:02 PMHow you managed to do that small button ?

CreateWindowEx() is your friend here.

QuoteAbout the listbos too, pls.

Ditto for that. Any window you want.

QuoteWhat i mean with syslistview, is the syslistview32 class and not the regular listbox.

I think you're confusing Microsoft's class name for the control (which is "SysListView32") with its commonly-used name, which is listview (as opposed to listbox, which is a much more primitive control).
Assembly language programming should be fun. That's why I do it.

guga

Indeed, i confused. It´s listview and not listbox.

Btw....Tks for the tip. I managed to work

The button is not that pretty yet, but at least it´s there.  :greenclp:  :greenclp:  :greenclp:



It´s a bit late right now. I´ll continue tomorrow. Tks a lot. It was really easy, and handy.

One question...is it affect flickering of the listview or problems of painting when you drag the columns etc ?
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com


guga

Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

NoCforMe

@Guga,

I'm curious to know how your project turned out. Did you get things all prettied up?

You might also want to take a look at DrawFrameControl(), if you don't already know about it. This can draw several standard Windows gizmos, like scroll buttons and pushbuttons. That's what I used in my program to draw things.
Assembly language programming should be fun. That's why I do it.

jj2007

Weird :rolleyes:
BOOL DrawFrameControl(
  [in] HDC    unnamedParam1,
  [in] LPRECT unnamedParam2,
  [in] UINT  unnamedParam3,
  [in] UINT  unnamedParam4

NoCforMe

Yes, weird: that's from the current version ("learn.microsoft.com ..."). I copied my help text from the earlier version ("MSDN"):

BOOL DrawFrameControl (
HDC hdc,
LPRECT lprc,
UINT uType,
UINT uState);

Guess the new version hides their identity to protect the innocent ...
Assembly language programming should be fun. That's why I do it.

guga

Hi JJ, Hi NoCForme

Here´s the skeleton of the app (plus the dlls in case it is needed). It do have the button as you said, but have small issues when i drag the column Painting problem perhaps or adjustment of position making the button appear duuplicated sometimes.

I´ll try to fix it, but before i´m porting (well, trying to) the project TimoVJL showed. It´s really amazing, although it uses listbox and not syslistview control, but i guess it can be very usefull.

Btw...the button does nothign yet...just show up on the proper position. Well..untill when we start to drag the columns :biggrin:  :biggrin:  :biggrin:  :biggrin:



On the src code (embedded in the file) i also adding some extra fucntions where i converted from C macros related to the controls. Things like ListBox_Dir, ListBox_GetCaretIndex, ListBox_GetSelCount etc. Those macros are the ones existent in windowsx.h. There are other macros too in CommCtrl.h from winSdk that should be excellent to port later. (It would be handy for Masm and also RosAsm)

A few examples of the converted C macros to RosAsm functions are:


; ListBox_InsertString(hwndCtl, index, lpsz)
Proc ListBox_InsertString:
    Arguments @hwndCtl, @index, @lpsz
    Uses ecx, edx

    call 'USER32.SendMessageA', D@hwndCtl, &LB_INSERTSTRING, D@index, D@lpsz

EndP

; ListBox_AddItemData(hwndCtl, data)
Proc ListBox_AddItemData:
    Arguments @hwndCtl, @data
    Uses ecx, edx

    call 'USER32.SendMessageA', D@hwndCtl, &LB_ADDSTRING, 0, D@data

EndP

; ListBox_InsertItemData(hwndCtl, index, data)
Proc ListBox_InsertItemData:
    Arguments @hwndCtl, @index, @data
    Uses ecx, edx

    call 'USER32.SendMessageA', D@hwndCtl, &LB_INSERTSTRING, D@index, D@data

EndP

; ListBox_DeleteString(hwndCtl, index)
Proc ListBox_DeleteString:
    Arguments @hwndCtl, @index
    Uses ecx, edx

    call 'USER32.SendMessageA', D@hwndCtl, &LB_DELETESTRING, D@index, 0

EndP

Shouldn´t be that hard port it to masm as well, since those macros are somewhat easier to read in C



Btw,...to add the btn to the syslist control i create a function like this:

Note: Don´t pay attention on the function name "GetCheckboxHandleInListView". It´s not a checkbox. I simply reused an old function i had named like that when i was testing to see if the button worked. I´ll rename it later.


Proc GetCheckboxHandleInListView:
    Arguments @Adressee, @hList, @RowIndex, @ColumnIndex
    Local @CheckBoxX, @CheckBoxY, @ButtonWidth, @ButtonHeight
    Structure @SubitemRect 24, @SubitemRect.leftDis 0, @SubitemRect.topDis 4, @SubitemRect.rightDis 8, @SubitemRect.bottomDis 12,
                               @Button.PointXDis 16, @Button.PointYDis 20
    Uses ecx, edx

    ; Get the item's rectangle
;    call ListView_GetItemRect D@hList, D@RowIndex, D@itemRect, &LVIR_BOUNDS

    ; Calculate the position of the checkbox within the item's rectangle
    ;int checkboxX = itemRect.left + columnIndex * 20; // Adjust as needed
    ;int checkboxY = itemRect.top + (itemRect.bottom - itemRect.top) / 2;

    call ListView_GetSubItemRect D@hList, D@RowIndex, D@ColumnIndex, &LVIR_BOUNDS, D@SubitemRect
    mov eax D@SubitemRect.bottomDis | sub eax D@SubitemRect.topDis | mov D@ButtonHeight eax
    mov D@ButtonWidth eax

    ; Calculate the position of the checkbox within the item's rectangle
    lea ecx D@Button.PointXDis
    mov eax D@SubitemRect.leftDis | mov D$ecx eax;mov D@CheckBoxX eax
    mov eax D@SubitemRect.topDis | mov D$ecx+4 eax
    ;mov eax D@SubitemRect.bottomDis | sub eax D@SubitemRect.topDis | shr eax 1 | add eax D@SubitemRect.topDis | mov D$ecx+4 eax;mov D@CheckBoxY eax

    ; Get the handle of the child window (checkbox) at the specified position

    call 'USER32.ChildWindowFromPoint' D@hList, ecx
    call 'USER32.CreateWindowExA' 0, {B$ "BUTTON", 0}, {B$ "...", 0}, &WS_CHILD__&WS_VISIBLE__&BS_PUSHBUTTON__&BS_FLAT,
                                  D@Button.PointXDis, D@Button.PointYDis, D@ButtonWidth, D@ButtonHeight,
                                  D@hList, &NULL, &NULL, &NULL
    ; Set the ListView as the parent of the button
    call 'USER32.SetParent' eax, D@hList

EndP

Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com