Войти

Показать полную графическую версию : mfc&& обработка передвижения ползунка полосы прокрутки


bezumes
23-01-2007, 18:24
Здравствуйте.У меня такая проблема. Есть диалоговое окошко, куда загружается изображение (bmp), эту картинку можно увеличивать,уменьшать, а также я хочу сделать, что если картинка увеличина(и её не всю видно) то можно было проскролить и увидеть остальную часть. Так вот при этом действии начинается моргание, а именно сначало картинка выводится в свой обычный размер(что не нужно),и сразу же нормальное изображение, И к тому же при передвижении картинки нужно както сделать, что бы при подходе к границе картинки дальше её нельзя было двигить?



void CscrenserverDlg::OnVScroll(UINT SBCode, UINT Pos,CScrollBar *SB)
{
// TODO: Add your message handler code here and/or call default
switch(SBCode)
{
case SB_BOTTOM:break ; //Прокрутка к нижней части.
case SB_ENDSCROLL:break; //Конечная прокрутка.
case SB_LINEDOWN:
scpos_y++;
break; // Листаю одну строку вниз.
case SB_LINEUP:
scpos_y--;
break; // Листаю одну строку вверх.
case SB_PAGEDOWN:
scpos_y+=10;break; // Листаю одну страницу вниз.
case SB_PAGEUP:
scpos_y-=10;
break; // Листаю одну страницу вверх.
case SB_THUMBPOSITION:break;// Прокрутка к абсолютной позиции.
case SB_THUMBTRACK:break; // Перетаскиваю бегунок к определенной позиции.
case SB_TOP:break; // Прокрутка к верхней части. */
}
// Устанавливаю новое состояние
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = scpos_y;
this->SetScrollInfo(SB_VERT, &si);
OnPaint();
CDialog::OnVScroll(SBCode, Pos, SB);
}






if(FileExt==CString("bmp"))
{
bm.Attach(LoadImage(0, CString(FileName),IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));
bm.GetObject(sizeof(BITMAP), &bmp);
GetClientRect(&Rect);
// Перетаскиваю битмап на окно c маштабированием
pDC->DrawState(CPoint(0,0),
CSize(bmp.bmWidth,bmp.bmHeight),bm, DST_BITMAP);
pDC->StretchBlt(0,-scpos_y,Rect.right*uve_x, (Rect.bottom-scpos_y)*uve_y, pDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
//вот в предыдущих трех строках и кроется корень всех зол, но искоренить его я не в состоянии.
bm.DeleteObject();
}

bezumes
24-01-2007, 16:52
сделал так

OnPaint();
CDC *pDC=GetDC();
CImage img;
CDC dcm;
dcm.CreateCompatibleDC(NULL);
if(FileExt==CString("bmp"))
{
bm.Attach(LoadImage(0, CString(FileName),IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));
bm.GetObject(sizeof(BITMAP), &bmp);
GetClientRect(&Rect);
// Перетаскиваю битмап на окно c маштабированием
dcm.SelectObject(&bm);
dcm.DrawState(CPoint(0,0),
CSize(bmp.bmWidth,bmp.bmHeight),bm, DST_BITMAP);
pDC->StretchBlt(0,-scpos_y,Rect.right*uve_x, (Rect.bottom-scpos_y)*uve_y, &dcm,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
bm.DeleteObject();
}
else
if(FileExt==CString("jpg"))
{
GetClientRect(&Rect);
img.Load(FileName);
HDC hdc;
// Получаю контекст устройства.
hdc=0;
hdc = pDC->GetSafeHdc();
// Показываю jpg-файл.
if(hdc!=0){
dcm.SelectObject(&img);
dcm.DrawState(CPoint(0,0),
CSize(img.GetWidth(),img.GetHeight()),img, DST_BITMAP);
img.StretchBlt(hdc,0,-scpos_y,Rect.right*uve_x,(Rect.bottom-scpos_y)*uve_y,SRCCOPY);
}
img.Destroy();
}
else
{
if(FileExt!=_T(""))
MessageBox(_T("Неверный формат файлов, надо bmp или jpg "));
FileExt=_T("");
}

проблема мерцания исчезла но вот это
И к тому же при передвижении картинки нужно как-то сделать, что бы при подходе к границе картинки дальше её нельзя было двигить? я не знаю как сделать

mrcnn
24-01-2007, 16:55
В книге Петцолда "Программирование в Windows" (Programming Windows) есть программы с обработкой полос прокрутки для окна.
В данном примере реализована и вертикальная и горизонтальная прокрутка. Может быть будет полезно раз вы обрабатываете события SB_LINEDOWN, SB_PAGEDOWN и т.д.?


/*----------------------------------------------------
SYSMETS3.C -- System Metrics Display Program No. 3
(c) Charles Petzold, 1996
----------------------------------------------------*/

#include <windows.h>
#include "sysmets.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "SysMets3" ;
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;

wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
RegisterClassEx (&wndclass) ;

hwnd = CreateWindow (szAppName, "Get System Metrics No. 3",
WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth,
iVscrollPos, iVscrollMax, iHscrollPos, iHscrollMax ;
char szBuffer[10] ;
HDC hdc ;
int i, x, y, iPaintBeg, iPaintEnd, iVscrollInc, iHscrollInc ;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;

switch (iMsg)
{
case WM_CREATE :
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
iMaxWidth = 40 * cxChar + 22 * cxCaps ;
return 0 ;


case WM_SIZE :
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;

iVscrollMax = max (0, NUMLINES + 2 - cyClient / cyChar) ;
iVscrollPos = min (iVscrollPos, iVscrollMax) ;

SetScrollRange (hwnd, SB_VERT, 0, iVscrollMax, FALSE) ;
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;

iHscrollMax = max (0, 2 + (iMaxWidth - cxClient) / cxChar) ;
iMaxWidth = 40 * cxChar + 22 * cxCaps ;
iHscrollPos = min (iHscrollPos, iHscrollMax) ;

SetScrollRange (hwnd, SB_HORZ, 0, iHscrollMax, FALSE) ;
SetScrollPos (hwnd, SB_HORZ, iHscrollPos, TRUE) ;
return 0 ;

case WM_VSCROLL :
switch (LOWORD (wParam))
{
case SB_TOP :
iVscrollInc = -iVscrollPos ;
break ;

case SB_BOTTOM :
iVscrollInc = iVscrollMax - iVscrollPos ;
break ;

case SB_LINEUP :
iVscrollInc = -1 ;
break ;

case SB_LINEDOWN :
iVscrollInc = 1 ;
break ;

case SB_PAGEUP :
iVscrollInc = min (-1, -cyClient / cyChar) ;
break ;

case SB_PAGEDOWN :
iVscrollInc = max (1, cyClient / cyChar) ;
break ;

case SB_THUMBTRACK :
iVscrollInc = HIWORD (wParam) - iVscrollPos ;
break ;

default :
iVscrollInc = 0 ;
}
iVscrollInc = max (-iVscrollPos,
min (iVscrollInc, iVscrollMax - iVscrollPos)) ;

if (iVscrollInc != 0)
{
iVscrollPos += iVscrollInc ;
ScrollWindow (hwnd, 0, -cyChar * iVscrollInc, NULL, NULL) ;
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
UpdateWindow (hwnd) ;
}
return 0 ;

case WM_HSCROLL :
switch (LOWORD (wParam))
{
case SB_LINEUP :
iHscrollInc = -1 ;
break ;

case SB_LINEDOWN :
iHscrollInc = 1 ;
break ;

case SB_PAGEUP :
iHscrollInc = -8 ;
break ;

case SB_PAGEDOWN :
iHscrollInc = 8 ;
break ;

case SB_THUMBPOSITION :
iHscrollInc = HIWORD (wParam) - iHscrollPos ;
break ;

default :
iHscrollInc = 0 ;
}
iHscrollInc = max (-iHscrollPos,
min (iHscrollInc, iHscrollMax - iHscrollPos)) ;

if (iHscrollInc != 0)
{
iHscrollPos += iHscrollInc ;
ScrollWindow (hwnd, -cxChar * iHscrollInc, 0, NULL, NULL) ;
SetScrollPos (hwnd, SB_HORZ, iHscrollPos, TRUE) ;
}
return 0 ;

case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;

iPaintBeg = max (0, iVscrollPos + ps.rcPaint.top / cyChar - 1) ;
iPaintEnd = min (NUMLINES,
iVscrollPos + ps.rcPaint.bottom / cyChar) ;

for (i = iPaintBeg ; i < iPaintEnd ; i++)
{
x = cxChar * (1 - iHscrollPos) ;
y = cyChar * (1 - iVscrollPos + i) ;

TextOut (hdc, x, y,
sysmetrics[i].szLabel,
strlen (sysmetrics[i].szLabel)) ;

TextOut (hdc, x + 22 * cxCaps, y,
sysmetrics[i].szDesc,
strlen (sysmetrics[i].szDesc)) ;

SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;

TextOut (hdc, x + 22 * cxCaps + 40 * cxChar, y,
szBuffer,
wsprintf (szBuffer, "%5d",
GetSystemMetrics (sysmetrics[i].iIndex))) ;

SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
}

EndPaint (hwnd, &ps) ;
return 0 ;

case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}

return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}

pva
28-01-2007, 17:40
Я не согласен с предложенным подходом. Мне больше нравится устанавливать минимальный 0, максимальный - размер показываемого поля и размер страницы - размер клиентской части окна + 1. Тогда:
1. есть индикация отношения видимой части к невидимой
2. когда видно всё, скролбары исчезают (автоматически)
для этого используется функция SetScrollInfo




© OSzone.net 2001-2012