The text in the SDK about using MapDialogRect & GetDialogBaseUnits is confusing.
The MapDialogRect function works correctly but the problem occurs if you need to convert pixels back into dialogbase units for say, saving to the registry.
SDK Quote ========================================
To convert these coordinates from dialog box units to pixels, the function retrieves the current horizontal and vertical base units for the dialog box, then applies the following formulas:
left = MulDiv(left, baseunitX, 4);
right = MulDiv(right, baseunitX, 4);
top = MulDiv(top, baseunitY, 8);
bottom = MulDiv(bottom, baseunitY, 8);
End Quote ========================================
where baseunitX is the average char width and baseunitY is the char height
however, playing around with this I found that the correct way is to use the following
pixels x = MulDiv(diagUnitX, tm.tmAveCharWidth-1, 4);
pixels y = MulDiv(diagUnitY, tm.tmAscent, 8);
You you are interested in proving it use the following code.
TEXTMETRIC tm;
HFONT hFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0);
HDC hdc = GetDC(hDlg);
GetTextMetrics(hdc, &tm);
ReleaseDC(hDlg, hdc);
RECT rc;
SetRect(&rc, 10, 40, 500, 340); // set the rect with coords
MapDialogRect(hDlg, &rc);
int left = MulDiv(10, tm.tmAveCharWidth-1, 4);
int top = MulDiv(40, tm.tmAscent, 8);
You will notice that even when using different size system fonts
left == rc.left
top == rc.top
Using tm.tmAveCharWidth and tm.tmHeight will give the wrong result.
I've tested this using two different PDI settings for the screen font.
And the conversion back to dialogbase units if you need to save these.
dialogbaseunitX = MulDiv(pixelX, 4, tm.tmAveCharWidth-1);
dialogbaseunitY = MulDiv(pixelY, 8, tm.tmAscent);
John