Hello, I am new to this forum and I will try to follow the correct protocol, but I apologize in advance if I do something wrong.
Graphics rotations using SetWorldTransform and StretchDIBits Windows API functions seems to have a problem in Pelles C V8 RC7.
I attach a sample code (full project attached as grbug.zip, main.c copied below) that displays a window with a bitmap in the center. The bitmap can be rotated using the keyboard left-right arrow keys. When the program is built with Pelles C V7 it behaves as expected. However, when it is built with Pelles C V8 RC7 the bitmap increases in size as it aproaches 45 degrees and then decreases to normal size in a ciclic way. It also shows some jerky behavior near a 45 degrees rotation.
Follows the code. The SetWorldTransform and StretchDIBits API functions are called from PaintWindow routine.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <tchar.h>
#include <stdlib.h>
#include <math.h>
#include "main.h"
static LRESULT WINAPI MainWndProc(HWND,UINT,WPARAM,LPARAM);
static void InitGraphs(void);
static void PaintWindow(void);
static HANDLE ghInstance;
static HWND hwndMain;
static LPBITMAPINFO lpBmpInfo;
static char *lpBmpData;
static HBITMAP hbm;
static float angle=0;
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
MSG msg;
ghInstance = hInstance;
wc.cbSize=sizeof(WNDCLASSEX);
wc.lpszClassName="Grbug";
wc.lpfnWndProc=MainWndProc;
wc.style=CS_OWNDC|CS_VREDRAW|CS_HREDRAW|CS_DBLCLKS;
wc.hInstance=ghInstance;
wc.hIcon=LoadIcon(ghInstance, MAKEINTRESOURCE(IDR_ICO_MAIN));
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hIconSm=NULL;
if (!RegisterClassEx(&wc))
return(1);
hwndMain=CreateWindow("Grbug",
"Graphics bug demo",
WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_MAXIMIZE,
0,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
ghInstance,
NULL
);
if (!hwndMain)
return(1);
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
for (;;)
{
BOOL fRet=GetMessage(&msg,NULL,0,0);
if (fRet==-1){
return(-1);
} else if (fRet == 0){
break;
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return(msg.wParam);
}
static LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch (msg){
case WM_CREATE:
InitGraphs();
return(0);
case WM_KEYDOWN:
switch (wParam){
case VK_LEFT:
angle+=0.05236;
if (angle>3.1416)
angle-=3.1416;
InvalidateRect(hwnd,NULL,TRUE);
UpdateWindow(hwnd);
break;
case VK_RIGHT:
angle-=0.05236;
if (angle<0)
angle+=3.1416;
InvalidateRect(hwnd,NULL,TRUE);
UpdateWindow(hwnd);
break;
default:
break;
}
return(0);
case WM_DESTROY:
PostQuitMessage(0);
return(0);
case WM_CLOSE:
if (lpBmpInfo!=NULL)
free(lpBmpInfo);
if (lpBmpData!=NULL)
free(lpBmpData);
DestroyWindow(hwnd);
return(0);
case WM_PAINT:
PaintWindow();
return(0);
default:
return(DefWindowProc(hwnd,msg,wParam,lParam));
}
}
static void InitGraphs(void)
{
HDC hdc;
int ii;
hdc=GetDC(hwndMain);
if (hdc==NULL)
return;
ii=GetDeviceCaps(hdc,RASTERCAPS);
if (((ii&RC_BITBLT)==0)||((ii&RC_STRETCHDIB)==0))
return;
lpBmpInfo=malloc((256*sizeof(RGBQUAD))+sizeof(BITMAPINFOHEADER));
if (lpBmpInfo==NULL)
return;
hbm=LoadBitmap(ghInstance,MAKEINTRESOURCE(IDR_BMP_MAIN));
lpBmpInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
lpBmpInfo->bmiHeader.biBitCount=0;
GetDIBits(hdc,hbm,0,0,NULL,lpBmpInfo,DIB_RGB_COLORS);
lpBmpData=malloc(lpBmpInfo->bmiHeader.biSizeImage);
if (lpBmpData==NULL)
return;
GetDIBits(hdc,hbm,0,lpBmpInfo->bmiHeader.biHeight,lpBmpData,lpBmpInfo,DIB_RGB_COLORS);
ReleaseDC(hwndMain,hdc);
return;
}
static void PaintWindow(void)
{
RECT rectclnt;
HDC hdc;
PAINTSTRUCT ps;
HRGN hRgn;
XFORM xform;
hdc=BeginPaint(hwndMain,&ps);
GetClientRect(hwndMain,&rectclnt);
hRgn=CreateRectRgnIndirect(&rectclnt);
SelectClipRgn(hdc,hRgn);
DeleteObject(hRgn);
SetGraphicsMode(hdc,GM_ADVANCED);
ModifyWorldTransform(hdc,&xform,MWT_IDENTITY);
ExtTextOut(hdc,rectclnt.left,rectclnt.top,ETO_CLIPPED|ETO_OPAQUE,&rectclnt," ",1,NULL);
xform.eM11=xform.eM22=cosf(angle);
xform.eM21=sinf(angle);
xform.eM12=-xform.eM21;
xform.eDx=(rectclnt.right+rectclnt.left)/2;
xform.eDy=(rectclnt.top+rectclnt.bottom)/2;
SetWorldTransform(hdc,&xform);
StretchDIBits(hdc,
-lpBmpInfo->bmiHeader.biWidth/2,
-lpBmpInfo->bmiHeader.biHeight/2,
lpBmpInfo->bmiHeader.biWidth,
lpBmpInfo->bmiHeader.biHeight,
0,
0,
lpBmpInfo->bmiHeader.biWidth,
lpBmpInfo->bmiHeader.biHeight,
lpBmpData,
lpBmpInfo,
DIB_RGB_COLORS,
SRCCOPY);
EndPaint(hwndMain,&ps);
return;
}
I apologize for the extension of the sample code, but even a very simple graphic program requires quite a lot of lines of code - at least with my admittedly poor programming skills.
In the meanwhile, is there any workaround for this problem?
Thanks for your help.