Skalowanie i odświeżanie miejscowe

0

Witam
Otóż od dłuższego czasu zmagam się z takim problemem a mianowicie dostaliśmy za zadanie stworzenie programu który miał odświezać tylko mały obszar obszaru klienckiego co by pozbyć się efektu migotania. Zrealizowałem to przy użyciu funkcji LPtoDP lecz niestety nie chodzi mi to do końca jak powinno, czy ktoś pomógłby mi znaleŹć rozwiązanie mojego problemu. Pozdrawiam

 
#include <Windows.h>
#define czarny 0
#define zolty 1
#define zielony 2
#define czerwony 3

TCHAR appName[] = TEXT("program");
TCHAR className[] = TEXT("klasa");

HBRUSH pedzle[4];
HPEN pioro;
unsigned char Plansza[60][60] = {0};
int playerx=30;
int playery=59; 
HDC hdcOkna;
void RysujPlansze(HDC hdcOkna)
{
	for(int i=0;i<60;++i)
	{
		for(int j=0;j<60;++j)
		{
			if(Plansza[i][j]==czarny) SelectObject(hdcOkna,pedzle[czarny]);
			if(Plansza[i][j]==zielony) SelectObject(hdcOkna,pedzle[zielony]);
			if(Plansza[i][j]==czerwony) SelectObject(hdcOkna,pedzle[czerwony]);
			if(Plansza[i][j]==zolty) SelectObject(hdcOkna,pedzle[zolty]);
			Rectangle(hdcOkna,10*i,10*j,10+10*i,10+10*j);
		}
	}
}
void Skaluj(HDC hdcOkna,HWND uchwyt)
{
	RECT R;
	GetClientRect(uchwyt,&R);
	SetMapMode(hdcOkna,MM_ISOTROPIC);
	SetWindowExtEx(hdcOkna,600,600,0);
	SetViewportExtEx(hdcOkna,R.right,R.bottom,0);
	SetViewportOrgEx( hdcOkna, 0, 0, NULL );
}


void RysujLudzik(HDC hdcOkna)
{
	Plansza[playerx][playery] = zielony;
}

void Przesun(HWND uchwyt,HDC hdcOkna, int dx,int dy)
{
	Plansza[playerx][playery] = czarny;
	RECT R;
	POINT a,b;
	playerx+=dx;
	playery+=dy;
	a.x=playerx*10;
	a.y=playery*10;
	b.x=10+playerx*10;
	b.y=10+playery*10;
	LPtoDP(hdcOkna,&a,1);
	LPtoDP(hdcOkna,&b,1);
	SetRect(&R,a.x,b.y,b.x,a.y);
	InvalidateRect(uchwyt,&R,TRUE);
}
LRESULT CALLBACK Obsluga(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_KEYDOWN:
		switch(wParam)
		{
		case VK_UP:
			Przesun(hWnd,hdcOkna,0,-1);
			break;
		case VK_DOWN:
			break;
		case VK_LEFT:
			break;
		case VK_RIGHT:
			break;
		}
		break;
	case WM_CREATE:
		pedzle[czarny] = CreateSolidBrush(RGB(0,0,0));
		pedzle[czerwony] = CreateSolidBrush(RGB(255,0,0));
		pedzle[zolty] = CreateSolidBrush(RGB(255,255,0));
		pedzle[zielony] = CreateSolidBrush(RGB(0,255,0));
		break;
	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			hdcOkna = BeginPaint(hWnd,&ps);
			int kopia = SaveDC(hdcOkna);
			Skaluj(hdcOkna,hWnd);
			RysujLudzik(hdcOkna);
			RysujPlansze(hdcOkna);
			EndPaint(hWnd,&ps);
			RestoreDC(hdcOkna,kopia);
			break;
		}
	case WM_DESTROY:
		for(int i=0;i<4;++i) DeleteObject(pedzle[i]);
		PostQuitMessage(0);
		break;
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
	default:
		return DefWindowProc(hWnd,msg,wParam,lParam);
	}
	return 0;
}

bool Rejestruj(WNDCLASSEX &wc, HINSTANCE &hInstance)
{
	wc.cbClsExtra=0;
	wc.cbSize=sizeof(WNDCLASSEX);
	wc.cbWndExtra=0;
	wc.hbrBackground = (HBRUSH ) (COLOR_WINDOW + 1);
	wc.hCursor=LoadCursor(NULL,IDC_ARROW);
	wc.hIcon=0;
	wc.hIconSm=0;
	wc.hInstance=hInstance;
	wc.lpfnWndProc=Obsluga;
	wc.lpszClassName=className;
	wc.lpszMenuName=appName;
	wc.style=CS_HREDRAW | CS_VREDRAW;

	if(!RegisterClassEx(&wc))
	{
		MessageBox(0,TEXT("Błąd rejestracji okna!"),TEXT("ERROR!"),MB_OK | MB_ICONERROR);
		return true;
	}
	return false;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevinstance, LPSTR LpCmdLine, int nShow)
{
	MSG msg;
	WNDCLASSEX wc;
	if(Rejestruj(wc,hInstance)) return 1;
	HWND okno=CreateWindowEx(0,className,appName,WS_OVERLAPPEDWINDOW,0,0,600,600,0,0,hInstance,0);
	if(!okno)
	{
		MessageBox(0,TEXT("Błąd funkcji RegisterClassEx!"),TEXT("ERROR!"),MB_OK | MB_ICONERROR);
		return 1;
	}

	ShowWindow(okno,nShow);
	UpdateWindow(okno);

	while(GetMessage(&msg,0,0,0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	UnregisterClass(className,hInstance);
	return msg.wParam;
}
0

Zrealizowałeś polecenie w połowie. Oznaczasz do odmalowania tylko ten fragment, który musi być odmalowany (InvalidateRect). Ale w odpowiedzi na komunikat WM_PAINT i tak malujesz wszystko. Musisz namalować tylko to, co znajduje się na oznaczonym obszarze. Granice obszaru do odmalowani możesz odczytać z pola rcPaint struktury PAINTSTRUCT po wywołaniu BeginPaint. Do dyspozycji są również funkcje GetUpdateRect i GetUpdateRgn.

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145193.aspx

0

Tak się składa że uruchamiając powyższy program nie odświeża się nic. A na samych wykładach była tylko mowa o funkcjach skalujących, InvalidateRect oraz LPtoDP i DPtoLP. Posiadam od kolegi kod gry która ma odświeżanie miejscowe i faktycznie to działa przy użyciu tego co wypisałem lecz nie mogę dojść do tego jak to działa.

0

Sprawdź, czy na pewno dobry prostokąt podajesz do InvalidateRect.

0

bool Rejestruj(WNDCLASSEX &wc, HINSTANCE &hInstance)
{
wc.cbClsExtra=0;

Nie czyścisz nigdzie wc. Być może tak naprawdę nie musisz, jeśli na pewno wypełniasz wszystkie pola struktury, ale łatwo o którymś polu zapomnieć…

1 użytkowników online, w tym zalogowanych: 0, gości: 1