Thumtrack Length Issue when resizing window with Image on Horizontal fit - c++

For Example: if my image width and height is 1600x2000 and client window width and height is 900x600.. now I want to fit the image horizontally. For that I will bring down the image width(1600) to window width(900) and also to maintain the original aspect ratio of the image i will also bring down the height of the image(2000) to 1125. for that I have used the below logic in FITHORIZONTAL Then I will use below wm_size code to set the scroll bar position and thumb length. Unfortunately the full image is not shown even though the thumb tracker has reached the end of the scroll bar.
switch(FitType)
{
case FITHORIZONTAL:
//find out whether resize percentage is decrease or increase
if(ActualImageWidth > WindowWidth) //resize decreasing
{
//find out the pecentage of decreased value
resizedPercent = WindowWidth/ActualImageWidth;
} else //resize increasing
{
//find out the pecentage of increased value
resizedPercent = ActualImageWidth/WindowWidth;
}
ResizedWidth = iWndwidth;
ResizedHeight = ActualImageHeight * resizedPercent;
break;
}
case WM_SIZE :
{
GetWindowRect(hWnd, &rect);
WndWidth = rect.right - rect.left;
WndHeight = rect.bottom - rect.top;
GetScrollInfo(hWnd, SB_VERT, &si);
int yMaxScroll = max((int)ResizedHeight - WndHeight, 0);
int yCurrentScroll = min(si.nPos, yMaxScroll);
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMin = 0;
si.nMax = ResizedHeight;
si.nPage = WndHeight;
si.nPos = 0;
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
InvalidateRect(hWnd, &rect, true);
return 0;
}

Related

DX9 switching from full screen to window give wrong client area

Having a bit of a problem in my dx9 application.
When I switch back from Full screen to windowed mode using the code below the client area is not the right size, it's smaller.
The AdjustWindowRect function is doing its task correctly but SetWindowPos does not set the right window size. Perhaps I'm missing something. Any ideas .
if (d3dpp.Windowed && resChoice == resolutionchoice) return false; // already in window mode and same resolution
//MessageBox(NULL, L"switching to window", L"ERROR", MB_OK);
resChoice = resolutionchoice;
screenWidth = resolutionwidth[resChoice];
screenHeight = resolutionheight[resChoice];
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // set the back buffer format to 32-bit
d3dpp.BackBufferWidth = screenWidth; // set the width of the buffer
d3dpp.BackBufferHeight = screenHeight; // set the height of the buffer
d3dpp.Windowed = true;
SetWindowLong(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); // WS_CAPTION | WS_SYSMENU | WS_VISIBLE | WS_MINIMIZEBOX );
// need to call SetWindowPos as well
string values;
RECT r = { 0,0,screenWidth,screenHeight };
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);
values = std::to_string(r.left);
OutputDebugStringA("Adjust area = ");
OutputDebugStringA(values.c_str()); OutputDebugStringA(",");
values = std::to_string(r.top);
OutputDebugStringA(values.c_str()); OutputDebugStringA(",");
values = std::to_string(r.right);
OutputDebugStringA(values.c_str()); OutputDebugStringA(",");
values = std::to_string(r.bottom);
OutputDebugStringA(values.c_str()); OutputDebugStringA("\n");
SetWindowPos(hWnd, HWND_TOP, r.left, r.top, r.right - r.left , r.bottom - r.top, SWP_NOZORDER | SWP_SHOWWINDOW | SWP_FRAMECHANGED);//
//screenWidth = SCREEN_WIDTH;
//screenHeight = SCREEN_HEIGHT;
//windowXscale = 1;
//windowYscale = 1;
GetClientRect(hWnd, &r);
values = std::to_string(r.left);
OutputDebugStringA("Client area = ");
OutputDebugStringA(values.c_str()); OutputDebugStringA(",");
values = std::to_string(r.top);
OutputDebugStringA(values.c_str()); OutputDebugStringA(",");
values = std::to_string(r.right);
OutputDebugStringA(values.c_str()); OutputDebugStringA(",");
values = std::to_string(r.bottom);
OutputDebugStringA(values.c_str()); OutputDebugStringA("\n");
}
After some more searching discovered that if you use SetWindowPos and attempt to make a window that is bigger than the desktop or when returning from Full screen in this case, windows will send a message and the window size will be adjusted automatically to make it no bigger than the current desktop size.
Adding SWP_NOSENDCHANGING flag in the SetWindowPos api call stops this happening and the client size will be what you wanted.

how to make a scrollable window in vc++ win32

basically I have a scrollbar in a custom window where we could add other controls like buttons, textboxes and so and so forth, now here is the problem I have created the scrollbar alright it scrolls down and up, but the problem is that the maximum scroll should be specified which then blocks it to scroll more than that, but there could be as much control as the user want, which for me it would not be known, I mean like to tell the problem to be more like a textbox's built-in scroll bar when you specify it with WM_VSCROLL OR HSCROLL, and then give the user the ability to scroll as much as you type on the textbox, that's exactly what I want.
here is the code so far I have been able to go through:-
Code for Scrollbar:-
case WM_LBUTTONDOWN:
{
SCROLLINFO si = { 0 };
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
si.nPos = 0;
si.nTrackPos = 0;
GetScrollInfo(hwnd, SB_VERT, &si);
break;
}
case WM_VSCROLL:
{
auto action = LOWORD(wParam);
HWND hScroll = (HWND)lParam;
int pos = -1;
if (action == SB_THUMBPOSITION || action == SB_THUMBTRACK) {
pos = HIWORD(wParam);
} else if (action == SB_LINEDOWN) {
pos = g_scrollY + 50;
} else if (action == SB_LINEUP) {
pos = g_scrollY - 50;
} else if (action == SB_PAGEUP) {
GetClientRect(hwnd, &r);
pos = g_scrollY - r.bottom;
} else if (action == SB_PAGEDOWN){
GetClientRect(hwnd, &r);
pos = g_scrollY + r.bottom;
}
if (pos == -1)
break;
SCROLLINFO si = { 0 };
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
si.nPos = pos;
si.nTrackPos = 0;
SetScrollInfo(hwnd, SB_VERT, &si, true);
GetScrollInfo(hwnd, SB_VERT, &si);
pos = si.nPos;
POINT pt;
pt.x = 0;
pt.y = pos - g_scrollY;
auto hdc = GetDC(hwnd);
LPtoDP(hdc, &pt, 1);
ReleaseDC(hwnd, hdc);
ScrollWindow(hwnd, 0, -pt.y, NULL, NULL);
g_scrollY = pos;
return 0;
}
case WM_SIZE:
{
RECT rc = { 0 };
GetClientRect(hwnd, &rc);
SCROLLINFO si = { 0 };
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
si.nMin = 0;
si.nMax = MAX_RANGE;
if(si.nPos > 100)
si.nMax = 5000;
if(SB_THUMBPOSITION == 100){
si.nMax = MAX_RANGE;}
si.nPage = (rc.bottom - rc.top);
si.nPos = 0;
si.nTrackPos = 0;
SetScrollInfo(hwnd, SB_VERT, &si, true);
break;
}
as you can see si.nMax value is the maximum amount of lines it is going to be able to scroll, but I want it to be as much as there are controls.
You must know how many controls are in your window, so you can set nMax member in the SCROLLINFO structure to whatever value you want and call SetScrollInfo() whenever new controls are added.

How to resize a Win32 listbox to fit its content?

Is there any way to resize a Win32 listbox to fit its content (the minimum size that will show all its content, not needing a scrollbar), whenever its items change?
Thank!
Edit: I need resize both width and height of listbox.
You didn't specify whether you wanted horizontal as well as vertical, but I'm going to assume not. Basically, you need to get the number of items and the item height and multiply them, then add on the space for the control borders (unless the control is borderless, you may need to play around with this):
void AutosizeListBox(HWND hWndLB)
{
int iItemHeight = SendMessage(hWndLB, LB_GETITEMHEIGHT, 0, 0);
int iItemCount = SendMessage(hWndLB, LB_GETCOUNT, 0, 0);
// calculate new desired client size
RECT rc;
GetClientRect(hWndLB, &rc);
rc.bottom = rc.top + iItemHeight * iItemCount;
// grow for borders
rc.right += GetSystemMetrics(SM_CXEDGE) * 2;
rc.bottom += GetSystemMetrics(SM_CXEDGE) * 2;
// resize
SetWindowPos(hWndLB, 0, 0, 0, rc.right, rc.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
}
If you want horizontal sizing as well you would need to select the right font into a DC, and loop through all the items to calculate the maximum text length using GetTextExtentPoint32.
EDIT: Added a version that calculates horizontal size as well.
void AutosizeListBox(HWND hWndLB)
{
int iItemHeight = SendMessage(hWndLB, LB_GETITEMHEIGHT, 0, 0);
int iItemCount = SendMessage(hWndLB, LB_GETCOUNT, 0, 0);
// get a DC and set up the font
HDC hDC = GetDC(hWndLB);
HGDIOBJ hOldFont = SelectObject(hDC, (HGDIOBJ)SendMessage(hWndLB, WM_GETFONT, 0, 0));
// calculate width of largest string
int iItemWidth = 0;
for (int i = 0; i < iItemCount; i++)
{
int iLen = SendMessage(hWndLB, LB_GETTEXTLEN, i, 0);
TCHAR* pBuf = new TCHAR[iLen + 1];
SendMessage(hWndLB, LB_GETTEXT, i, (LPARAM)pBuf);
SIZE sz;
GetTextExtentPoint32(hDC, pBuf, iLen, &sz);
if (iItemWidth < sz.cx) iItemWidth = sz.cx;
delete[] pBuf;
}
SelectObject(hDC, hOldFont);
ReleaseDC(hWndLB, hDC);
// calculate new desired client size
RECT rc;
SetRect(&rc, 0, 0, iItemWidth, iItemHeight * iItemCount);
// grow for borders
rc.right += GetSystemMetrics(SM_CXEDGE) * 2;
rc.bottom += GetSystemMetrics(SM_CXEDGE) * 2;
// resize
SetWindowPos(hWndLB, 0, 0, 0, rc.right, rc.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
}

Calculate ideal font size, based on the paper size and maximum allowed text length

I have printing code that draws grid on the paper.
Grid has 4 columns, and they have equal horizontal length. Height of the cell is tenth of the paper size. Total number of rows is unknown but I know for a fact that there will be at least one row.
Each cell has same physical size-> width is quarter of the paper width, and height is one tenth of the paper height. Maximum number of characters that can fit into cell is 50.
The problem I face is choosing proper font size so text of maximum length can fit into cell.
Browsing through MSDN documentation and WinAPI examples, I saw that they use GetTextExtPoint32 for similar purposes, but this works only if font already exists and is selected into device context, which is not the case here.
The only thing that crossed my mind was to create "dummy font", see if the example text can fit into cell, and then adjust it's size if the test fails. I have also found this blog that recommends interesting approach to this problem, but being inexperienced I can't decide if "this is the proper way to go".
Can you recommend a correct solution for my problem?
EDITED on June, 30th 2014:
Below is the sample function that draws grid and paints upper left cell in light gray since that cell will contain sample text. That way we can visually validate the success of our drawing code:
// hWnd is the window that owns the property sheet.
HRESULT GDI_PRINT(HWND hWnd)
{
HRESULT hResult;
PRINTDLGEX pdx = {0};
LPPRINTPAGERANGE pPageRanges = NULL;
// Allocate an array of PRINTPAGERANGE structures.
pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
if (!pPageRanges)
return E_OUTOFMEMORY;
// Initialize the PRINTDLGEX structure.
pdx.lStructSize = sizeof(PRINTDLGEX);
pdx.hwndOwner = hWnd;
pdx.hDevMode = NULL;
pdx.hDevNames = NULL;
pdx.hDC = NULL;
pdx.Flags = PD_RETURNDC;
pdx.Flags2 = 0;
pdx.ExclusionFlags = 0;
pdx.nPageRanges = 0;
pdx.nMaxPageRanges = 10;
pdx.lpPageRanges = pPageRanges;
pdx.nMinPage = 1;
pdx.nMaxPage = 1000;
pdx.nCopies = 1;
pdx.hInstance = 0;
pdx.lpPrintTemplateName = NULL;
pdx.lpCallback = NULL;
pdx.nPropertyPages = 0;
pdx.lphPropertyPages = NULL;
pdx.nStartPage = START_PAGE_GENERAL;
pdx.dwResultAction = 0;
// Invoke the Print property sheet.
hResult = PrintDlgEx(&pdx);
if ( ( hResult == S_OK ) && ( pdx.dwResultAction == PD_RESULT_PRINT ) )
{
// User clicked the Print button,
// so use the DC and other information returned in the
// PRINTDLGEX structure to print the document.
//======= Various initializations ==========//
DOCINFO diDocInfo = {0};
diDocInfo.cbSize = sizeof( DOCINFO );
diDocInfo.lpszDocName = L"Testing printing...";
int pageWidth = GetDeviceCaps( pdx.hDC, HORZRES ),
pageHeight = GetDeviceCaps( pdx.hDC, VERTRES );
//===================== IMPORTANT !!! ==========================//
// Must test this on real printer !!! //
// For now testing is done in XPS and MS OneNote2007 //
//==============================================================//
//================== end of initialization =====================//
if( StartDoc( pdx.hDC, &diDocInfo ) > 0 )
{
if( StartPage( pdx.hDC ) > 0 )
{
//===== creating red pen that will draw grid =====//
LOGBRUSH lb;
lb.lbColor = RGB( 255, 0, 0 );
lb.lbHatch = 0;
lb.lbStyle = BS_SOLID;
HPEN hPen = ExtCreatePen( PS_COSMETIC | PS_SOLID, 1, &lb, 0, NULL);
HGDIOBJ oldPen = SelectObject( pdx.hDC, hPen );
// create test font
HFONT font, oldFont;
long lfHeight = -MulDiv( 14,
GetDeviceCaps( pdx.hDC, LOGPIXELSY ),
72 );
font = CreateFont( lfHeight, 0, 0, 0,
FW_BOLD, TRUE, FALSE, FALSE,
0, 0, 0,
0, 0, L"Microsoft Sans Serif" );
oldFont = SelectFont( pdx.hDC, font );
SetBkMode( pdx.hDC, TRANSPARENT );
SetTextColor( pdx.hDC, RGB( 255, 0, 0 ) );
// testing rectangle -> top left cell of the grid
RECT rcText;
rcText.left = 0;
rcText.top = 0;
rcText.right = pageWidth / 4;
rcText.bottom = pageHeight / 10;
// fill destination rectangle with gray brush
// so we can visually validate rectangle coordinates
FillRect( pdx.hDC, &rcText, (HBRUSH)GetStockObject(LTGRAY_BRUSH) );
// implement solution mentioned in the comment to this question
SIZE s;
::GetTextExtentPoint32( pdx.hDC,
L"Хидрогеотермална енергија Хидрогеотермална енерги",
wcslen( L"Хидрогеотермална енергија Хидрогеотермална енерги" ),
&s );
// select old font back and dispose test font
SelectObject( pdx.hDC, oldFont );
DeleteObject( font );
// adjust font height
lfHeight *= s.cy / ( rcText.bottom - rcText.top );
// now we can create proper font
font = CreateFont( lfHeight, 0, 0, 0,
FW_BOLD, TRUE, FALSE, FALSE,
0, 0, 0,
0, 0, L"Microsoft Sans Serif" );
oldFont = SelectFont( pdx.hDC, font );
// draw text in test rectangle
DrawTextEx( pdx.hDC,
L"Хидрогеотермална енергија Хидрогеотермална енерги",
wcslen( L"Хидрогеотермална енергија Хидрогеотермална енерги" ),
&rcText, DT_CENTER | DT_WORDBREAK | DT_NOCLIP, NULL );
//============== draw a testing grid ===============//
// draw vertical lines of the grid
for( int i = 0; i <= pageWidth; i += pageWidth / 4 )
{
MoveToEx( pdx.hDC, i, 0, NULL );
LineTo( pdx.hDC, i, pageHeight );
}
// draw horizontal lines of the grid
for( int j = 0; j <= pageHeight; j += pageHeight / 10 )
{
MoveToEx( pdx.hDC, 0, j, NULL );
LineTo( pdx.hDC, pageWidth, j );
}
// no need for pen anymore so delete it
SelectObject( pdx.hDC, oldPen );
DeleteObject( hPen );
// no need for font, delete it
SelectFont( pdx.hDC, oldFont );
DeleteFont( font );
if( EndPage( pdx.hDC ) < 0 )
// for now pop a message box saying something went wrong
MessageBox( hWnd, L"EndDoc failed!", L"Error", MB_OK );
}
EndDoc( pdx.hDC );
}
}
if (pdx.hDevMode != NULL)
GlobalFree(pdx.hDevMode);
if (pdx.hDevNames != NULL)
GlobalFree(pdx.hDevNames);
if (pdx.lpPageRanges != NULL)
GlobalFree(pPageRanges);
if (pdx.hDC != NULL)
DeleteDC(pdx.hDC);
return hResult;
}
To use this function, just launch it on button press/menu selection or whatever.
The results in XPS seem consistent, but I get strange results in MS OneNote 2007 which following images illustrate:
Font size is 14 :
Font size is 20 :
Font size is 20, but scaling from the above function was applied :
END OF EDIT
EDITED on July, 6th 2014:
The third picture from above edit was the result of GDI using default height value because the result of my mathematical adjustment for font height was 0. Once zero is passed to CreateFont mentioned behavior is expected.
After performing proper casting from double to int I got nearly perfect output -> last letter in the string barely exceeds the limit. I will continue to try improving this formula since I believe is promising. If anybody has another mathematical solution feel free to post it.
END OF EDIT
If further info / edit is required, leave a comment and I will react as soon as possible.
There are multiple issues involved.
The biggest problem I see is in this line:
lfHeight *= s.cy / ( rcText.bottom - rcText.top );
These are all integers. In C and C++, division with integers results in truncation toward zero. So if the result of the division "should" be 3.7, you'll end up with 3, which can be a pretty crude approximation.
Another problem is that GetTextExtentPoint32 does not wrap text, but DrawText does. So you're measuring the text as though you're going to print it as a single line, and you actually draw it as multiple lines. Instead of using GetTextExtendPoint32, you can measure the height with DrawText by DT_CALCRECT flag.
Putting these together, you want to measure your text like this:
WCHAR szText[] = L"Хидрогеотермална енергија Хидрогеотермална енерги";
RECT rcText;
rcText.left = 0;
rcText.top = 0;
rcText.right = pageWidth / 4;
rcText.bottom = top;
const DWORD options = DT_CENTER | DT_WORDBREAK | DT_NOCLIP;
DrawTextEx( pdx.hDC, szText, -1, &rcText, options | DT_CALCRECT, NULL);
// Because we used DT_CALCRECT, the DrawTextEx call didn't draw anything,
// but it did adjust the bottom of rcText to account for the actual height.
double actual_height = static_cast<double>(rcText.bottom - rcText.top);
double desired_height = pageHeight / 10.0;
double ratio = desired_heigth / actual_height;
// Scale the font height by the ratio, and round it off to the nearest int.
lf.lfHeight = static_cast<int>(lf.lfHeight * ratio + 0.5);
Okay. Basically, I start off with the suggested pointSize (14 in your code) and try to draw the text using the supplied bounding rect. If the text is too large, I go into an iterative loop that decreases the pointsize and measures again until the text will fit into the bounding rect.
If, on the other hand, the text is 'too small' I go into a loop that gradually increases it's size until it is too large. Once I reach this point, I decrease the point-size by 2 and return.
The reduction by 2 is a kludge or hack. I noticed that at times the size was reported as being equal to or smaller than the reported size of the bounding rect, yet still some characters would protrude past the edge of the bounding rect.
A better solution would make use of the DrawTextEx function to both calculate the size and draw the text. This would be better since you could make use of the iLeftmargin and iRightMargin members of the DRAWTEXTPARAMS struct that is passed to that function. Whether you wished to have a margin on each side, or simply wanted to add a single character's width, that you then halved when drawing the text would depend entirely on the desired outcome. I also added the DT_EXTERNALLEADING flag to obtain a small margin above/below the text, though there isn't one for vertical padding, so you'd have to make use of the margin attributes I mention.
Since the DT_VCENTER flag doesn't work with multi-line text, you'd also need to vertically offset the text yourself if you wished it to be vertically centered. You'd just have to offset the rect used for actually drawing the text by half of the difference between the area bounding rect's height and the text bounding rect's height.
I could have used a function like this for a few projects, so thanks for the impetus to actually exercise the grey matter and work it out!
Lastly, I used an interactive demo - one that responded to the WM_PAINT message of a (empty) dialog box. Since a HDC can be treated more-or-less the same whether it be for a printer or the screen, it provided a much quicker way of investigating the result.
Output when plugged into your code: (via cutePDF virtual printer)
Code:
int rectWidth(RECT &r)
{
return (r.right - r.left) + 1;
}
int rectHeight(RECT &r)
{
return (r.bottom - r.top) + 1;
}
void measureFunc(int pointSize, HDC hdc, RECT &pRectBounding, WCHAR *textToDraw, WCHAR *fontFaceName, int &resultWidth, int &resultHeight)
{
int pixelsPerInchY = GetDeviceCaps(hdc, LOGPIXELSY);
int logHeight = -MulDiv(pointSize, pixelsPerInchY, 72);
RECT tmpRect = pRectBounding;
HFONT old, tmp = CreateFont( logHeight, 0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE, 0, 0, 0, 0, 0, fontFaceName );
old = (HFONT)SelectObject(hdc, tmp);
DrawText(hdc, textToDraw, -1, &tmpRect, DT_CENTER | DT_WORDBREAK | DT_NOCLIP | DT_CALCRECT| DT_EXTERNALLEADING );
SelectObject(hdc, old);
DeleteObject(tmp);
resultWidth = rectWidth(tmpRect);
resultHeight = rectHeight(tmpRect);
}
HFONT getMaxFont(HDC hdc, WCHAR *fontName, WCHAR *textToDraw, RECT boundingRect)
{
int maxWidth = rectWidth(boundingRect), maxHeight = rectHeight(boundingRect);
int curWidth, curHeight, pointSize=14;
measureFunc(pointSize, hdc, boundingRect, textToDraw, fontName, curWidth, curHeight);
if ( (curWidth>maxWidth) || (curHeight>maxHeight) )
{
bool tooLarge = true;
while (tooLarge)
{
pointSize--;
measureFunc(pointSize, hdc, boundingRect, textToDraw, fontName, curWidth, curHeight);
if ((curWidth>maxWidth)||(curHeight>maxHeight))
tooLarge = true;
else
tooLarge = false;
}
}
else
{
bool tooSmall = true;
while (tooSmall)
{
pointSize++;
measureFunc(pointSize, hdc, boundingRect, textToDraw, fontName, curWidth, curHeight);
if ( (curWidth<maxWidth) && (curHeight<maxHeight) )
tooSmall = true;
else
tooSmall = false;
}
if ((curWidth>maxWidth) || (curHeight>maxHeight))
{
pointSize-=2;
}
}
int pixelsPerInchY = GetDeviceCaps( hdc, LOGPIXELSY );
int curFontSize;
HFONT result;
curFontSize = -MulDiv(pointSize, pixelsPerInchY, 72);
result = CreateFont(curFontSize, 0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE, 0, 0, 0, 0, 0, fontName );
return result;
}
BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
}
return TRUE;
case WM_SIZE:
InvalidateRect(hwndDlg, NULL, true);
return 0;
case WM_ERASEBKGND:
{
RECT mRect;
GetClientRect(hwndDlg, &mRect);
HBRUSH redBrush = CreateSolidBrush(RGB(255,0,0));
FillRect((HDC)wParam, &mRect, redBrush);
DeleteObject(redBrush);
}
return true;
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
HFONT requiredFont, oldFont;
WCHAR *textToDraw = L"Хидрогеотермална енергија Хидрогеотермална енерги";
WCHAR *fontFace = L"Microsoft Sans Serif";
RECT boundingRect, dlgRect;
hdc = BeginPaint(hwndDlg, &ps);
oldFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
GetClientRect(hwndDlg, &dlgRect);
SetRect(&boundingRect, 0,0, rectWidth(dlgRect) / 4, rectHeight(dlgRect) / 10);
FillRect(hdc, &boundingRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
requiredFont = getMaxFont(hdc, fontFace, textToDraw, boundingRect);
SelectObject(hdc, requiredFont);
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, textToDraw, -1, &boundingRect, DT_CENTER | DT_WORDBREAK | DT_NOCLIP | DT_EXTERNALLEADING );
SelectObject(hdc, oldFont);
DeleteObject(requiredFont);
EndPaint(hwndDlg, &ps);
}
return false;
case WM_CLOSE:
{
EndDialog(hwndDlg, 0);
}
return TRUE;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
}
}
return TRUE;
}
return FALSE;
}

how to attach scrollbar to a dialog

I have to find the correct way to attach a scrollbar to a set of images that are created dynamically by the application.
In my code I create the scrollbar but it is not working properly. The main window does not scroll to view all the images.
int currentLength = iImage * (WIDTH + SPACER);
picName.Format(_T("Image %d"),iImage);
CPoint topLeft(currentLength,0);
CPoint bottomRigth(currentLength + (WIDTH), HEIGHT);
CRect miniCRect(topLeft, bottomRigth);
Miniature[iImage] = new CStatic();
Miniature[iImage]->Create(picName, WS_CHILD|WS_VISIBLE|SS_BITMAP, miniCRect, this);
if((bottomRigth.x > 500) && (currentLength <= 500))
{
//creo la scrool bar
CPoint ptnrigin(0,210);
CPoint endptn(bottomRigth.x,230);
CRect workingArea(ptnrigin,endptn);
cs.Create(WS_VISIBLE,workingArea,this,0);
cs.EnableScrollBar(ESB_ENABLE_BOTH);
SCROLLINFO info;
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
info.nMin = 1;
info.nMax = 10;
info.nPage = 2;
info.nPos = 5;
info.nTrackPos = 5;
cs.SetScrollInfo(&info);
}
HDC hDCScreen_mini = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
HDC hDCMem_mini = ::CreateCompatibleDC(hDCScreen_mini);
// create a compatible bitmap and select it in the memory DC
HBITMAP hBitmap_mini = ::CreateCompatibleBitmap(hDCScreen_mini, miniCRect.Width(), miniCRect.Height());
HBITMAP hBmpOld_mini = (HBITMAP)::SelectObject(hDCMem_mini, hBitmap_mini);
BitBlt(hDCMem_mini, 0, 0, desktopRect.Width(), desktopRect.Height(), hDCScreen_mini, desktopRect.left, desktopRect.top, dwRop);
Miniature[iImage]->SetBitmap(hBitmap_mini);
Invalidate();
// restore the memory DC and perform cleanup
SelectObject(hDCMem_mini, hBmpOld_mini);
DeleteDC(hDCMem_mini);
DeleteDC(hDCScreen_mini);
//end capture
Can someone help me?
A scrollbar does not scroll your window or its contents. It only provides input from the user to code that you must write to reposition the images. Such code typically uses ScrollWindow to move the visible portion, followed by adding the newly-visible portion in WM_PAINT.
A different approach (that does do the scrolling for you) would be to put the images in an owner-drawn list box.