Ownerdrawn items

With ownerdrawn items M!Table provides a way to custom paint cells, column headers, column header groups, row headers and the table corner.
To custom paint an item, first of all declare it as ownerdrawn with MTblSetOwnerDrawnItem . Once an item is ownerdrawn, every time when it must be painted MTM_DrawItem is sent to the table. On this message call MTblGetOwnerDrawnItem to get required information in an instance of fcMTblODI and paint whatever you want.

Functions
MTblGetOwnerDrawnItem
MTblIsOwnerDrawnItem
MTblSetOwnerDrawnItem

Classes
fcMTblODI

Messages
MTM_DrawItem


Types and function parameters


Type constant

Affected item(s)

Function parameter
hWndParam

Function parameter
nParam

MTBL_ODI_CELL

A cell

Column handle

Row number

MTBL_ODI_COLUMN

The header and the cells of a column

Column handle

TBL_Error

MTBL_ODI_COLHDR

A column header

Column handle

TBL_Error

MTBL_ODI_COLHDRGRP

A column header group

Table handle

Column header group ID

MTBL_ODI_ROW

The header and the cells of a row

Table handle

Row number

MTBL_ODI_ROWHDR

A row header

Table handle

Row number

MTBL_ODI_CORNER

The corner

Table handle

TBL_Error



Hints and tips

Printing
M!Table also sends MTM_DrawItem when you print a table with MTblPrint. In this case the fcMTblODI instance variable Printing is TRUE.
Keep in mind that printers normally have another resolution ( dots per inch ) than the screen. fcMTblODI has specific instance variables to handle this problem, namely YResFactor and XResFactor, e.g.

 

Screen resolution

Printer resolution

ResFactor

X

96 DPI

300 DPI

3.125 ( 300 / 96 )

Y

96 DPI

600 DPI

6.25 ( 600 / 96 )

To get the same sizes and/or positions as on the screen, use the following formulas:
Font Size Printer = Font Size Screen * YResFactor
Pixels X Printer = Pixels X Screen * XResFactor
Pixels Y Printer = Pixels Y Screen * YResFactor

The item rectangle ( instance variables Left, Top, Right and Bottom ) and the leadings ( instance variables XLeading and YLeading ) are already in printer units, so don't multiply them with the resolution factors!

Furthermore, please note that drawing (semi-) transparent images with the MImgDraw functions does not work as on the screen. The transparent parts appear black!
To avoid this, call MImgStripOpacity to strip the transparency with the desired background color before drawing.

Drawing into the column and/or row line area
The item rectangle doesn't include the column and/or row line area. If you want to paint into the column line area, simply add 1 to fcMTblODI.Right. If you want to paint into the row line area, simply add 1 to fcMTblODI.Bottom, e.g:

On MTM_DrawItem
  ...
  ! Let's paint a blue background and "remove" the column and row line
  Set nColor = COLOR_Blue
  Set nBrush = CreateSolidBrush( nColor )
  Set nOldBrush = SelectObject( odi.DC, nBrush )
  Call FillRect( odi.DC, odi.Left, odi.Top, odi.Right + 1, odi.Bottom + 1, nBrush )
  Call SelectObject( odi.DC, nOldBrush )
  Call DeleteObject( nBrush )

Please note that you can't "remove" lines that way when the table is printed because in the printout the grid lines are always painted according to the value of fcMTblPrintParams.GridType after the custom painting is done.

Selections
Normally, you don't have to concern about selections because MTM_DrawItem is sent before M!Table inverts the selected rows and/or columns.

But if selection colors are used ( see MTblSetSelectionColors or Extended selections ), M!Table doesn't invert the selected rows and/or columns, but draws them with the defined selection colors.
If you want to reflect selections in your ownerdrawn items, you have to determine the correct text and background color.
Check if the fcMTblODI instance variable Selected is TRUE and if selection colors are used. If so, use the selection colors, e.g.:
...
Call MTblGetEffCellTextColor( odi.HWndParam, odi.NParam, nTextColor )
Call MTblGetEffCellBackColor( odi.HWndParam, odi.NParam, nBackColor )
If odi.Selected And Not odi.Printing
  Call MTblGetSelectionColors( hWndTbl, nSelTextColor, nSelBackColor )
  If nSelTextColor != MTBL_COLOR_UNDEF
    Set nTextColor = nSelTextColor
  If nSelBackColor != MTBL_COLOR_UNDEF
    Set nBackColor = nSelBackColor
...    

Automatic sizing
To ensure a proper automatic sizing for your ownerdrawn items ( e.g. if you call MTblAutoSizeColumn ), you should return appropriate values on MTM_QueryBestCellWidth and/or MTM_QueryBestColHdrWidth. Let's say you have an ownerdrawn cell in which you draw a rectangle with a width of 200 pixels, then you should do something like this:
On MTM_QueryBestCellWidth
  If MTblIsOwnerDrawnItem( SalNumberToWindowHandle( wParam ), lParam, MTBL_ODI_CELL )
    Return 210 ! 10 pixels margin
  Else
    Return 0 ! Not ownerdrawn, let M!Table determine the best width

 

Created with the Personal Edition of HelpNDoc: Produce electronic books easily