2016-06-30 9 views
-1

So habe ich für eine Weile mit diesem Problem der Bildgrößenanpassung festgefahren: Das Programm zeigt ein Bild an und verkleinert es dann entsprechend der vom Benutzer beim Ziehen des Rands bereitgestellten Größe, anstatt das Bild zu beschneiden Bild, wenn der Rahmen nach innen gezogen wird oder wenn er nach außen gezogen wird.Bildgrößenanpassung: Welche Korrekturen sollte ich vornehmen? (Fensteranwendung, VC++)

Ich habe einen Anzeigefensteralgorithmus in der Haupt-WinAPI verwendet und die Deklaration einer Instanz des Skalierungsalgorithmus in WM_PAINT bereitgestellt.

Ich muss den Skalierungsalgorithmus von einer separaten Klasse aus einer separaten Datei im selben Projekt verknüpfen, die ich in die Kopfzeile eingefügt habe (#include "scaling.h"). Nach dem Skalieren des Bildes habe ich die Anzeige wieder im Fenster aufgerufen, aber nach dem Ziehen des Randes ändert sich die Größe nicht. Welche Änderungen müsste ich an dem Code vornehmen?

#include <windows.h> 
#include <windows.h> 
#include <tchar.h> 
#include "scaling.h" 
HBITMAP hBitmap; 
HDC localDC; 
HBITMAP hOld; 
BITMAP qB; 
HDC hDC;            // Handle (virtual memory pointer) to drawing characteristics 
RECT rect; 
PAINTSTRUCT ps; 
HDC MemDC; 
HBITMAP bmp; 
BITMAP bm; 

LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam){ 
switch(msg){ 
    case WM_CREATE:{ 
     //MessageBox(hwnd,_T("Window Procedure Received WM_CREATE Message!"),_T("Message Report!"),MB_OK); 
     return 0; 
    } 
    case WM_LBUTTONDOWN: { 
     //MessageBox(hwnd,_T("Window Procedure Received WM_LBUTTONDOWN Message!"),_T("Message Report!"),MB_OK); 
    return 0; 
    } 

    case WM_PAINT: {     //At program start up the whole window is invalid so must be drawn. 
     //TCHAR tmpText[]=_T("TempText"); 
     PAINTSTRUCT ps;  
     hDC = BeginPaint(hwnd,&ps); 
     BOOL qRetBlit = ::BitBlt(hDC,0,0,qB.bmWidth,qB.bmHeight,localDC,0,0,SRCCOPY); 

     ::GetClientRect(hwnd, &rect); 

     // Create a memory device compatible with the above DC variable 
     MemDC = CreateCompatibleDC(hDC); 

     // Select the new bitmap 
     SelectObject(MemDC, hBitmap); 
     GetObject(hBitmap, sizeof(bm), &bm); 

     int w2,h2; 
     if(GetClientRect(hwnd, &rect)) //In order to obtain the current window's parameters 
     { 
      w2 = rect.right - rect.left; 
      h2 = rect.bottom - rect.top; 
     } 

     BYTE *pixels_old = (BYTE *)qB.bmBits; 
     scaling sc; 
     BYTE *pixels = sc.resizePixels(pixels_old, qB.bmWidth, qB.bmHeight, w2, h2); 

     qB.bmBits = pixels; 

     MemDC = CreateCompatibleDC(hDC); 

     SelectObject(MemDC, &qB); 

     hDC = BeginPaint(hwnd,&ps); 
     qRetBlit = ::BitBlt(hDC,w2,h2,qB.bmWidth,qB.bmHeight,localDC,0,0,SRCCOPY); 

     delete []pixels; 
            // Return Drawing Context To Original State 
     EndPaint(hwnd, &ps); 
     return 0; 
    } 
    case WM_DESTROY: {      
     ::SelectObject(localDC,hOld); 
     ::DeleteDC(localDC); 
     ::DeleteObject(hBitmap); 
     PostQuitMessage(0); 
     return 0; 
    } 
} 
return (DefWindowProc(hwnd, msg, wParam, lParam)); 
} 


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int iShow){ 
TCHAR szClassName[]=_T("Name"); 
WNDCLASSEX wc; 
MSG messages; 
HWND hWnd; 

wc.lpszClassName = szClassName;      
wc.lpfnWndProc = fnWndProc;      
wc.cbSize   = sizeof (WNDCLASSEX);    
wc.style   = 0;        
wc.hIcon   = LoadIcon(NULL,IDI_APPLICATION); 
wc.hInstance  = hInstance;      
wc.hIconSm  = 0; //LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 
wc.hCursor  = LoadCursor(NULL,IDC_ARROW);  
wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;   
wc.cbWndExtra  = 0;        
wc.cbClsExtra  = 0; 
wc.lpszMenuName = NULL; 
RegisterClassEx(&wc); 
hBitmap = (HBITMAP)::LoadImage(NULL, _T("D:\\Chrysanthemum.bmp"),IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION); 
GetObject(reinterpret_cast<HGDIOBJ>(hBitmap),sizeof(BITMAP),reinterpret_cast<LPVOID>(&qB)); 
localDC = ::CreateCompatibleDC(hDC); 
hOld = (HBITMAP)::SelectObject(localDC,hBitmap); 

hWnd = CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,0,0,qB.bmWidth,qB.bmHeight,HWND_DESKTOP,0,hInstance,0); 
ShowWindow(hWnd,iShow); 
while(GetMessage(&messages,NULL,0,0)){             
    TranslateMessage(&messages);      
    DispatchMessage(&messages); 
} 
return (int)messages.wParam; 
} 

Der Skalierungsalgorithmus von "Scaling.h" ist wie folgt: (nächste Nachbar)

#include <iostream> 
class scaling{ 
public: 
BYTE* resizePixels(BYTE* pixels,int w1,int h1,int w2,int h2) 
{ 
    BYTE* retval = new BYTE[w2*h2] ; 
// EDIT: added +1 to remedy an early rounding problem 
int x_ratio = (int)((w1<<16)/w2) +1; 
int y_ratio = (int)((h1<<16)/h2) +1; 
//int x_ratio = (int)((w1<<16)/w2) ; 
//int y_ratio = (int)((h1<<16)/h2) ; 
int x2, y2 ; 
for (int i=0;i<h2;i++) { 
    for (int j=0;j<w2;j++) { 
     x2 = ((j*x_ratio)>>16) ; 
     y2 = ((i*y_ratio)>>16) ; 
     retval[(i*w2)+j] = pixels[(y2*w1)+x2] ; 
    }     
}     
return retval; 
} 
}; 

Vielen Dank im Voraus!

+0

Ich bin überrascht, dass dies alles was auch immer anzeigt. Ihr 'SelectObject (MemDC, & qB)' übergibt einen Zeiger und nicht ein Handle, also sollte es überhaupt nicht funktionieren. –

+0

Es zeigt nur den ersten Teil an, nicht das skalierte Bild. Hmm, ich werde das mal sehen, danke. –

Antwort

0
+0

Ich habe bereits einen Algorithmus zum Zweck der Skalierung gewählt, nur etwas in meiner Implementierung ist vermasselt. –

+0

Link-Only-Antworten werden nicht akzeptiert. Einige Ihrer Links scheinen überhaupt nicht relevant zu sein. Bitte siehe http://stackoverflow.com/help/how-to-answer –

0

Verwendung StretchBlt seine Leichtigkeit. Ich denke, das ist ein Fehler in Ihrem Stretch-Algorithmus.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd145120(v=vs.85).aspx

+0

Ah, ich habe es schon mit StretchBlt gemacht. Die Aufgabe, die mir gegeben wurde, bestand darin, eine Funktion aus einer anderen Datei zum Dehnen aufzurufen. Der Stretching-Part funktioniert (ich habe einige Dateioperationen durchgeführt und herausgefunden, dass sich die Größe tatsächlich so ändert, wie ich es wollte, aus den Werten, die ich später zu w2, h2 hinzugefügt habe). Es stimmt also etwas mit dem Display nicht. –

+0

In Ihrem Code ist ein Fehler enthalten. trage hDC in deinem Code auf. Sie rufen BeginPaint zweimal an! Versuchen Sie, schreibe von scratchю – Alexandr

+0

Ah danke! Wie auch immer, ich habe BeginPaint entfernt, aber ich nehme an, dass qRetBlit noch einmal aufgerufen werden muss, oder? –