Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.02.2013, 19:21   #1
gunsoy
Форумчанин
 
Регистрация: 30.12.2010
Сообщений: 280
Вопрос При скроллинге разрывается изображение

Здравствуйте
Нашел в интерете код для скроллинга Окно прокручивается нормально Но возникают проблемы с изображением находящимся в моем окне
Если при прокрутке скроллинга изображение зайдет за видимую часть окна, то при обратной прокрутке та часть изображения которая находилась за окном разрывается
Подскажите пожалуйста в чем моя ошибка
gunsoy вне форума Ответить с цитированием
Старый 01.02.2013, 19:22   #2
gunsoy
Форумчанин
 
Регистрация: 30.12.2010
Сообщений: 280
По умолчанию

SCROLLINFO hScroll = {0};
SCROLLINFO vScroll ={0};
RECT RC;

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rt;
int i;
static int x, y;
static POINT pts[3];
static HDC memDC;
static HBITMAP hPicture;
static BITMAP bm;
int p = 3000;



switch (message) /* handle the messages */
{
case WM_CREATE:
SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG) CreateSolidBrush(RGB(0,0,0)) );
hPicture = (HBITMAP)LoadImage(hInst, "Ginkgo.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

InvalidateRect(hwnd, NULL, TRUE);
break;

case WM_SIZE:
GetClientRect(hwnd, &RC);
hScroll.cbSize = sizeof(SCROLLINFO);
hScroll.fMask = SIF_RANGE;
hScroll.nMin = 0;
hScroll.nMax = p - RC.right;
SetScrollInfo(hwnd, SB_HORZ, &hScroll, TRUE);


vScroll.cbSize = sizeof(SCROLLINFO);
vScroll.fMask = SIF_RANGE;
vScroll.nMax =p - RC.bottom;
vScroll.nMin = 0;
SetScrollInfo(hwnd, SB_VERT, &vScroll, TRUE);

InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);

break;


case WM_PAINT:
hScroll.cbSize = sizeof(SCROLLINFO);
hScroll.fMask = SIF_POS;
GetScrollInfo(hwnd, SB_HORZ, &hScroll);

vScroll.cbSize =sizeof(SCROLLINFO);
vScroll.fMask = SIF_POS;
GetScrollInfo(hwnd, SB_VERT, &vScroll);
GetClientRect(hwnd, &RC);



x = 0;
y = 20;
hdc = BeginPaint(hwnd, &ps);
for(i = 0; i < 30; i++)
{
GetObject(hPicture, sizeof(bm), &bm);
GetClientRect(hwnd, &rt);
pts[0].x = x;
pts[0].y = y;
x += 20;
y -= 20;
pts[1].x = x;
pts[1].y = y;
y += 40;
pts[2].y = y;
pts[2].x = x;
memDC = CreateCompatibleDC(hdc);
SelectObject(memDC, hPicture);
PlgBlt(hdc, pts, memDC, 0, 0, bm.bmWidth, bm.bmHeight, 0, 0, 0);
DeleteDC(memDC);
}
EndPaint(hwnd, &ps);
break;
gunsoy вне форума Ответить с цитированием
Старый 01.02.2013, 19:26   #3
gunsoy
Форумчанин
 
Регистрация: 30.12.2010
Сообщений: 280
По умолчанию

case WM_HSCROLL:
{
int HSp,HSp1;
SCROLLINFO hScroll;
hScroll.cbSize = sizeof(SCROLLINFO);
hScroll.fMask = SIF_POS| SIF_RANGE | SIF_TRACKPOS;
GetScrollInfo(hwnd, SB_HORZ, &hScroll);

RECT RC;
GetClientRect(hwnd, &RC);


switch (LOWORD(wParam))
{
case SB_LINERIGHT:
case SB_PAGERIGHT:
{
HSp1 =(LOWORD(wParam) == SB_LINERIGHT) ? 10 : RC.right;
HSp = hScroll.nMax - hScroll.nPos;
if(HSp>HSp1) HSp=HSp1;
hScroll.nPos = hScroll.nPos + HSp;
break;
}
case SB_LINELEFT:
case SB_PAGELEFT:
{
HSp1 =(LOWORD(wParam) == SB_LINELEFT) ? 10 : RC.right;
HSp = hScroll.nPos - hScroll.nMin;
if(HSp>HSp1) HSp=HSp1;
HSp = -HSp;
hScroll.nPos = hScroll.nPos + HSp;
break;

}
case SB_THUMBTRACK:
{
HSp = hScroll.nTrackPos-hScroll.nPos;
hScroll.nPos=hScroll.nTrackPos;
break;
}

}

hScroll.cbSize=sizeof(SCROLLINFO);
hScroll.fMask = SIF_POS;
ScrollWindowEx(hwnd, -HSp, 0, NULL, NULL, NULL, NULL, SW_ERASE);

if(HSp > 0)
RC.left = RC.right - HSp;
else
RC.right = RC.left - HSp;

SetScrollInfo(hwnd,SB_HORZ, &hScroll, TRUE);
InvalidateRect(hwnd, &RC, TRUE);
UpdateWindow(hwnd);
return 0;


}

case WM_VSCROLL:
{
SCROLLINFO vScroll;
vScroll.cbSize = sizeof(SCROLLINFO);
vScroll.fMask = SIF_POS | SIF_RANGE | SIF_TRACKPOS;
GetScrollInfo(hwnd, SB_VERT, &vScroll);

RECT RC;
GetClientRect(hwnd, &RC);

int VSp,VSp1;
switch (LOWORD(wParam))
{
case SB_LINEDOWN:
case SB_PAGEDOWN:
{
VSp1= (LOWORD(wParam) == SB_LINEDOWN)? 10 : RC.bottom;
VSp = vScroll.nMax - vScroll.nPos;
if(VSp>VSp1)VSp=VSp1;
vScroll.nPos = vScroll.nPos + VSp;
break;
}
case SB_LINEUP:
case SB_PAGEUP:
{ VSp1= (LOWORD(wParam) == SB_LINEUP)? 10 : RC.bottom;
VSp = vScroll.nPos - vScroll.nMin;
if(VSp>VSp1) VSp = VSp1;
VSp=-VSp;
vScroll.nPos = vScroll.nPos +VSp;
break;
}
case SB_THUMBTRACK:
{
VSp =vScroll.nTrackPos - vScroll.nPos;
vScroll.nPos = vScroll.nTrackPos;
break;
}
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);

}
vScroll.cbSize = sizeof(SCROLLINFO);
vScroll.fMask = SIF_POS;
ScrollWindowEx(hwnd, 0, -VSp, NULL, NULL, NULL, NULL, SW_ERASE);

if (VSp>0)
RC.top = RC.bottom - VSp;
else
RC.bottom = RC.top -VSp;

SetScrollInfo(hwnd, SB_VERT, &vScroll, TRUE);
InvalidateRect(hwnd, &RC, TRUE);
UpdateWindow(hwnd);
return 0;

}
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}
gunsoy вне форума Ответить с цитированием
Старый 03.02.2013, 04:50   #4
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Да много ошибок. Разрывается изображение потому, что нет инвалидации нужной области. Но и сам подход к скроллингу какой-то кривой. Загрузив картинку, надо бы сразу ставить максимумы скроллов и больше их не менять. И при ресайзе окна менять только размер nPage.
И при WM_VSCROLL/WM_HSCROLL какие-то ненужные сложности.

Вот как бы я написал:

Код:
#include <windows.h>
#include <gdiplus.h>
#pragma comment (lib, "gdiplus.lib")

using namespace Gdiplus;

#define SIMPLESTRING TEXT("SIMPLESTRING")
#define MENUCOMMAND1 7777 

LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam,  LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_SIZE:
		// при ресайзе окна менять только размер ползуна
		{
		    SCROLLINFO si = { sizeof(SCROLLINFO), SIF_PAGE };
		    si.nPage = LOWORD(lParam);
		    SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
		    si.nPage =  HIWORD(lParam);
		    SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
		    InvalidateRect(hwnd, NULL, FALSE);
		}
		break;
	case WM_HSCROLL:
	case WM_VSCROLL:
		int nNewPos;
		nNewPos =  GetScrollPos (hwnd, uMsg == WM_HSCROLL ? SB_HORZ : SB_VERT);
		switch (LOWORD(wParam))
		{
			case SB_THUMBTRACK: 
			case SB_THUMBPOSITION:
				nNewPos = HIWORD(wParam); 
				break;
			case SB_PAGELEFT:                           
				nNewPos -= 20;
				break;
			case SB_PAGERIGHT: 
				nNewPos += 20; 
				break;
			case SB_LINERIGHT:
				nNewPos += 1;
				break;
			case SB_LINELEFT:
				nNewPos -= 1;
				break;
			case SB_ENDSCROLL: 
				InvalidateRect(hwnd, NULL, TRUE);
				return TRUE; 
		}
		SetScrollPos(hwnd, uMsg == WM_HSCROLL ? SB_HORZ : SB_VERT, nNewPos, TRUE); 
		InvalidateRect(hwnd, NULL, TRUE);
		break;
	case WM_COMMAND:
		if (! HIWORD (wParam)) // команда меню
		{
			if (LOWORD (wParam)== MENUCOMMAND1)
			{
			    wchar_t FILENAME [MAX_PATH] = {};
			    OPENFILENAMEW ofn = {sizeof(OPENFILENAMEW)};
			    ofn.hwndOwner = hwnd;
			    ofn.lpstrFile = FILENAME;
			    ofn.nMaxFile = MAX_PATH;
			    // Открыть диалог выбора файла
			    if (GetOpenFileNameW(&ofn))
			    {	// Создать новую
			        Bitmap* ptr = new Bitmap(FILENAME);
			        // Убить предыдущую картинку
			        delete (Bitmap*) GetProp(hwnd, SIMPLESTRING);
			        // Сохранить картинку в свойствах окна
			        SetProp(hwnd, SIMPLESTRING,(HANDLE) ptr);
			        // Установить максимумы скроллов равными габаритам картинки
			        SetScrollRange(hwnd, SB_HORZ, 0, ptr->GetWidth(), TRUE);
			        SetScrollRange(hwnd, SB_VERT, 0, ptr->GetHeight(), TRUE);
			    }
			}
		}
		break;
	case WM_ERASEBKGND:
		return 0; // фон окна рисовать в WM_PAINT
	
	case WM_PAINT:
		PAINTSTRUCT ps;
		BeginPaint (hwnd, &ps);
		{
			// Запросить сохраненную картинку 
			Bitmap* ptr = (Bitmap*) GetProp(hwnd, SIMPLESTRING);
			// текущие позиции скролла
			int X = - GetScrollPos(hwnd, SB_HORZ);
			int Y = - GetScrollPos(hwnd, SB_VERT);
			// сохранить состояние контекста
			int r = SaveDC(ps.hdc);
			if (ptr) // удалить из области отсечения текущие координаты картинки
				ExcludeClipRect (ps.hdc, X, Y, ptr->GetWidth() + X, ptr->GetHeight() + Y);
			// нарисовать фон вне области картинки
			FillRect(ps.hdc, &ps.rcPaint, GetSysColorBrush(COLOR_3DFACE)); 
			// восстановить область отсечения
			RestoreDC(ps.hdc, r);
			// нарисовать картинку с учетом координат скролла
			Graphics G(ps.hdc);
			G.DrawImage(ptr, X, Y);
		}
		EndPaint(hwnd, &ps);
		break;
	case WM_DESTROY:
		delete (Bitmap*) RemoveProp (hwnd, SIMPLESTRING);
		PostQuitMessage(0); 
		break;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
		
	// Инициализировать GDIPLUS
	GdiplusStartupInput input;
	GdiplusStartupOutput output;
	ULONG dwToken;
	GdiplusStartup(&dwToken, &input, &output);

	// Зарегистрировать класс окна
	WNDCLASS wc = {};
	wc.lpfnWndProc = WindowProc;
	wc.lpszClassName = SIMPLESTRING;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	RegisterClass(&wc);
	
	// Создать меню Файл->Открыть
	HMENU hmnu = CreateMenu();
	HMENU hmnu2 = CreateMenu();
	InsertMenu(hmnu2, 0, 0, MENUCOMMAND1, TEXT("Открыть"));
	InsertMenu(hmnu, 0, MF_POPUP, (UINT_PTR) hmnu2, TEXT("Файл"));

	// Создать окно
	HWND hwndmain = CreateWindow(SIMPLESTRING, SIMPLESTRING, 
		WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
		CW_USEDEFAULT, CW_USEDEFAULT, 
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, hmnu, hInstance, NULL);
	
	// Отобразить окно
	ShowWindow(hwndmain, SW_SHOW);
	UpdateWindow(hwndmain);
	
	MSG msg;  // Главный цикл
	while(GetMessage(&msg, NULL, 0, 0))
		DispatchMessage(&msg);
	
	// Убить меню
	DestroyMenu(hmnu);
	DestroyMenu(hmnu2);
	return 0;
}

Последний раз редактировалось EUGY; 03.02.2013 в 05:56. Причина: чуток поправил
EUGY вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Плавное движение липкого блока при скроллинге xDyPx JavaScript, Ajax 9 23.01.2013 09:13
Почему при инверсии изображения, оно (изображение) исчезает? Blame Мультимедиа в Delphi 1 02.10.2012 21:11
показать изображение при UserForm1.Show 0 Blame Microsoft Office Excel 5 17.02.2012 01:15
Обрезать изображение при экране 800х600 Kapitann HTML и CSS 0 14.09.2010 01:01