Bodmoor
2017-12-15T14:10:41Z
Hello,

I want to draw a 'button' in a grid, that changes appearance on mouseover. I can detect the mouseover, and call the drawcell method, but that does not trigger the CustomDrawCell event. I think that this is happening because I am triggering an event from another event, but how can I avoid this?
Igor/10Tec
2017-12-16T09:19:21Z
We need a sample to see this problem. Can you reproduce the problem in a simple project and send it to us?
Bodmoor
2017-12-18T08:39:07Z
  exampleDB.zip (63kb) downloaded 21 time(s).

Hello,

Attached is a demo project, where I will draw a button to the right of the column. I have added debug.print statements, to show when certain events occur, so that you can see that when calling the drawcell method from mousemove, the customdrawcell is not triggered. A button only appears as long as the mouse button remains down, and the moue does not move.

I have a workaround using a timer to trigger the drawcell event, but this leaves my code cluttered and vulnerable.

In my opinion it would be an nice addition to be able to draw a button, or another image, on mousedown and mouseover events. If I can only update the icon that I can already display, I can show feedback to the user and 'simulate' a button since the click on an icon can already be detected without additional coordinate checking. I would really like that feature, as it would make this example obsolete.

Kind regards, Paul
Igor/10Tec
2017-12-18T15:37:12Z
I copied your code to a VB6 project and it works flawlessly there. In fact you found one more glitch of MS Access, when corresponding events of an ActiveX control are not raised as expected. Other customers already encountered this problem, and we know how to solve it:

iGrid events are not always raised in MS Access 

I applied that fix to your code, and it seems, now it works ok. Here is the modified version of your db with this fix:

  exampleDB2.zip (28kb) downloaded 24 time(s).

I see you are using WinAPI regions in your code a lot. According to the MSDN documentation for the CreateRectRgn  function, you should call the WinAPI DeleteObject function to delete a region if you no longer need it. Improve your code by calling DeleteObject for every region you create with CreateRectRgn to avoid memory leak problems.

I will also move this thread to the MS Access section  as it is a specific discussion related to the usage of iGrid inside MS Access.
Bodmoor
2017-12-19T15:32:08Z
Hello,

Thanks for the alternative, this is working great. Customdrawcell is triggered by the drawcell method, which allows me to do some drawing.

I also discovered the drawimage call using the matching image list, but decided to draw the images myself. For anyone interested:


Public Declare Function GdipCreateBitmapFromFile Lib "GDIPlus" (ByVal filename As Long, bitmap As Long) As Long
Public Declare Function GetObjectA Lib "gdi32" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Public Declare Function GdipCreateHBITMAPFromBitmap Lib "GDIPlus" (ByVal bitmap As Long, hbmReturn As Long, ByVal background As Long) As Long
Public Declare Function DeleteDC Lib "GDI32.DLL" (ByVal hdc As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long

Public Function DrawImage(hdc As Long, x, y, strFile As String, bgColor As Long)
Dim bmp As Long, hBitmap As Long, hBitmapOld As Long
Dim lResult As Long, pSource As Long
Dim tBMP As bitmap

    lResult = GdipCreateBitmapFromFile(StrPtr(strFile), bmp)

    If nul(lResult) Then
        lResult = GdipCreateHBITMAPFromBitmap(bmp, hBitmap, bgColor)

        pSource = CreateCompatibleDC(hdc)
        hBitmapOld = SelectObject(pSource, hBitmap)

        GetObjectA hBitmap, Len(tBMP), tBMP

        Call BitBlt(hdc, x, y, tBMP.bmWidth, tBMP.bmHeight, pSource, 0, 0, 13369376)     '= TernaryRasterOperations.SRCCOPY
    End If
    
    DeleteDC pSource
    DeleteObject hBitmap
    DeleteObject hBitmapOld

End Function


this allows me to, when properly controlled using mousemove, down and leave events, create a button that changes its appearance.


Private Sub gdGrid_CustomDrawCell(ByVal lRow As Long, ByVal lCol As Long, ByVal hdc As Long, ByVal lLeft As Long, ByVal lTop As Long, ByVal lRight As Long, ByVal lBottom As Long, ByVal bSelected As Boolean)
Dim rc As rect
Dim val As String
Dim indentCorrection As Integer

    val = gdGrid.CellValue(lRow, lCol)
    
    indentCorrection = gdGrid.LevelIndent * (gdGrid.RowLevel(lRow))
    
    With rc
        .left = lLeft + indentCorrection + 2
        .Top = lTop + 2
        .Bottom = lBottom
        .right = lRight
    End With

    DrawText hdc, val, Len(val), rc, DT_LEFT
    
    If bSelected Then
    
         With rc
            .left = lLeft - 2
            .Top = lTop - 2
            .Bottom = lBottom
            .right = lRight
        End With
        
        If mouseover Then
            'iGridGetImageList.DrawImageAlpha "btn_hover", hdc, rc.right - 18, 2, 255  '0 to 255"
            DrawImage hdc, rc.right - 22, 1, "C:\temp\button_hover_19.png", gdGrid.CellEffectiveBackColor(lRow, lCol)
        ElseIf mousedown Then
            'iGridGetImageList.DrawImageAlpha "btn_pressed", hdc, rc.right - 18, 2, 255 '0 to 255"
            DrawImage hdc, rc.right - 22, 1, "C:\temp\button_pressed_19.png", gdGrid.CellEffectiveBackColor(lRow, lCol)
        Else
            'iGridGetImageList.DrawImageAlpha "btn_normal", hdc, rc.right - 18, 2, 255  '0 to 255
            DrawImage hdc, rc.right - 22, 1, "C:\temp\button_normal_19.png", gdGrid.CellEffectiveBackColor(lRow, lCol)
        End If
   End If
End Sub