Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   mfc&& обработка передвижения ползунка полосы прокрутки (http://forum.oszone.net/showthread.php?t=78087)

bezumes 23-01-2007 18:24 540251

mfc&& обработка передвижения ползунка полосы прокрутки
 
Здравствуйте.У меня такая проблема. Есть диалоговое окошко, куда загружается изображение (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 540692

сделал так
Код:

        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 540694

В книге Петцолда "Программирование в 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 542691

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


Время: 06:05.

Время: 06:05.
© OSzone.net 2001-