Evgenios1 Δημοσ. 18 Ιανουαρίου 2010 Δημοσ. 18 Ιανουαρίου 2010 Βασικα δεν μπορω να καταλαβω ακομα πως ακριβος δουλευει αυτη η μηχανη. Διαβασα σχετικα με αυτη και εκανα μια προσπαθεια να ζωγραφισω μια γραμμη και πετυχε. Τωρα ομως θελω να φτιαξω ενα paint app, απλα πραματα, να ζωγραφιζω με το ποντικι. Ο κωδικας ειναι 5 γραμμες, αλλα για καποιο λογο δεν ζωγραφιζει οταν το βαλω στο win mess mousemove. Παραθετω το κωδικα μπας και μου εξηγησει κανεις για ποιο λογο δεν κανει αυτο που θελω στο Mouse event. >LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; [color="Blue"] case WM_MOUSEMOVE: { if(wParam == MK_LBUTTON) { hdc = BeginPaint(hWnd, &ps); HPEN hPen = CreatePen(0,5,RGB(22,111,22)); hPen = (HPEN)SelectObject(hdc,hPen); MoveToEx(hdc,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y,0); LineTo(hdc,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); EndPaint(hWnd, &ps); } } break;[/color] default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
GCMH Δημοσ. 18 Ιανουαρίου 2010 Δημοσ. 18 Ιανουαρίου 2010 Μια παρατηρήση μιας και δεν ξέρω από C. Να μάθω και κάτι... Όταν ζωγραφίζεις μια γραμμή, δεν θα πρέπει αφετερία και τέλος να διαφέρουν τουλάχιστον κατά ένα; πχ moveto(...x,y) lineto(...x+1,y)
bxenos Δημοσ. 18 Ιανουαρίου 2010 Δημοσ. 18 Ιανουαρίου 2010 ... >HPEN hPen = CreatePen(0,5,RGB(22,111,22)); [color="Red"]/*hPen = (HPEN)*/[/color]SelectObject(hdc,hPen); το hpen είναι handle, μην το ξανααποθηκευεις...δεν χρειάζεται Ελεγξε και τις τιμές που πέρνεις ακόμα και αν είσαι σίγουρος για το οτι θα παρεις σωστο αποτέλεσμα π.χ. > #include <assert.h> ... HPEN hPen = CreatePen(0,5,RGB(22,111,22)); assert(hPen!=NULL); ... τις παραμέτρους του raw win32 gdi δεν τις θυμάμε απ'εξω, καθότι έχω objects να κάνουν αυτή τη δουλεια για μένα εδω και αρκετό καιρό, αν δεν βγάλεις άκρη, πες να ψάξω τι είχα γραψει στα class αυτά.
Evgenios1 Δημοσ. 18 Ιανουαρίου 2010 Μέλος Δημοσ. 18 Ιανουαρίου 2010 Δεν μπορω να καταλαβω γιατι οταν βαλω τον ιδο ακριβος κωδικα στο wm_paint δουλευει ενω στο wm_mousemove δεν.
bxenos Δημοσ. 18 Ιανουαρίου 2010 Δημοσ. 18 Ιανουαρίου 2010 Ωπ, καμπανάκια χτυπάνε Εδωσες την απάντηση μόνος σου. An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call to the EndPaint function. απο εδώ. Αν δεν κάνω λάθος θέλει CreateDC για ζωγραφισμα έξω απο WM_PAINT, θα το δω και θα σου πω. Φυσικά παίζει και με invalidateRect (θα σου έρθει μετά στο WM_PAINT). ---------- Προσθήκη στις 23:09 ---------- Προηγούμενο μήνυμα στις 23:03 ---------- Ένα κομάτι απο κώδικα που χρησιμοποιώ για ζωγράφισμα εκτός wm_paint. > int mdisplay::__GetDC(){ register HDC hdc = GetDC((HWND)owner()->getHwnd()); massert(((HDC)(mword)hdc) == hdc);//check for data loss set_hdc((mword)hdc); return hdc ? TRUE : FALSE; } void mdisplay::__ReleaseDC(){ if(hdc()){ int bReleased = ReleaseDC((HWND)owner()->getHwnd(),(HDC)hdc()); #ifdef _DEBUG //if(_u_winapi_getFlag("ReleaseDCLog",FALSE)){ // writeDebug( // "ReleaseDC(owner=%x, hdc=%x, returned %s)\n", // (mword)owner()->getHwnd(), // (mword)hdc(), // bReleased ? "RELEASES" : "NOT RELEASED" // ); //} #endif set_hdc(NULL); } } Αυτές είναι οι low level συναρτησεις του class που χρησιμοποιώ σε windows. Θα βγάλεις άκρη πιστευώ, εχω κρατήσει και τα "ονόματα" των windows (hdc,hwnd...) στα εσωτερικά members
Evgenios1 Δημοσ. 18 Ιανουαρίου 2010 Μέλος Δημοσ. 18 Ιανουαρίου 2010 Ωραια αφου θελει να ειναι στο WM_PAINT τοτε γτ δεν δουλευει αυτο? >LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; case ID_FILE_TEST: { } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: { [color="blue"] hdc = BeginPaint(hWnd, &ps); assert(hdc!=NULL); HPEN hPen = CreatePen(PS_SOLID,50,RGB(22,111,22)); SelectObject(hdc,hPen); assert(hPen != NULL); if(lParam!=NULL){ MoveToEx(hdc,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y,NULL); LineTo(hdc,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); } EndPaint(hWnd, &ps);[/color] } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_MOUSEMOVE: { if(wParam == MK_LBUTTON) { [color="Blue"]SendMessage(hWnd,WM_PAINT,0,lParam);[/color] } } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
bxenos Δημοσ. 18 Ιανουαρίου 2010 Δημοσ. 18 Ιανουαρίου 2010 Δεν μπορείς να στείλεις SendMessage με WM_PAINT. Το WM_PAINT κάνει και clipping στο invalid rect αρα δεν έχεις InvalidRect αρα δεν μπορείς να ζωγραφίσεις. Μονο το InvalidateRect θα ετοιμάσει σωστα το WM_PAINT. Ο κώδικας με CreateDC/ReleaseDC δεν σου κάνει; Τρεχει οπουδήποτε, όχι μονο σε WM_PAINT.
Directx Δημοσ. 19 Ιανουαρίου 2010 Δημοσ. 19 Ιανουαρίου 2010 Με πρόλαβε ο bxenos -- Μίας και έχω καιρό να ασχοληθώ με καθαρό WinAPI (ελέω .NET/VCL/Qt) αποφάσισα να γραψω το πρόγραμμα έτσι ώστε να σχεδιάζει πάνω σε ένα Bitmap (Backbuffer) το οποίο θα κάνει BitBlt στην επιφάνεια (DC) του παραθύρου ώστε τα περιεχόμενα να διατηρούνται συνεχώς. Το δεξί πλήκτρο του Mouse καθαρίζει ολόκληρο το παράθυρο. Το πρόγραμμα σχεδιάζει αμέσως με το πάτημα του αριστερού πλήκτρου του Mouse στο παράθυρο ένα Line ώστε να μην είναι απαραίτητη η μετακίνηση του mouse (βλ. WM_LBUTTONDOWN). Το πρόγραμμα έχει δοκιμασθεί επιτυχώς σε C++ Builder 2009, φυσικά μπορεί να υπάρχουν σφάλματα ή άλλες αβλεψίες. > /* * Simple Draw using Bitmap by directx. */ #include <windows.h> #ifdef __BORLANDC__ #pragma hdrstop #endif #define MYCLASS "MYCLASS" //--------------------------------------------------------------------------- LRESULT CALLBACK WProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); #ifdef __BORLANDC__ #pragma argsused #endif WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { /* Setup window class. */ WNDCLASS WC; ZeroMemory(&WC, sizeof(WC)); WC.lpfnWndProc = (WNDPROC)WProc; WC.style = CS_HREDRAW | CS_VREDRAW; WC.hInstance = hInstance; WC.hCursor = LoadCursor(NULL, IDC_ARROW); WC.hbrBackground = GetStockObject(WHITE_BRUSH); WC.lpszClassName = MYCLASS; if(!RegisterClass(&WC)) { MessageBox(NULL, "RegisterClass failed!", NULL, MB_ICONSTOP); return 1; } /* Setup window. */ HWND hWnd = CreateWindow(MYCLASS, "Draw", WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL); if(hWnd == NULL) MessageBox(NULL, "CreateWindow error!", NULL, MB_ICONSTOP); else { MSG myMsg; /* Kickstart window. */ ShowWindow(hWnd, SW_NORMAL); UpdateWindow(hWnd); /* Setup window message-loop (not the MS way!). */ while(GetMessage(&myMsg, NULL, 0, 0)) { TranslateMessage(&myMsg); DispatchMessage(&myMsg); } } /* End of program. */ return 0; } //--------------------------------------------------------------------------- LRESULT CALLBACK WProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { static POINT Pos; static HDC hSurfaceDC = NULL; static HPEN hPen = NULL, hPenBak = NULL; static HBITMAP hSurface = NULL; static RECT rcClient; PAINTSTRUCT PS; POINT POS; HDC hDC; switch(Msg) { case WM_CREATE: /* Grab window bitmap. */ if((hDC = GetDC(hWnd)) == NULL) { MessageBox(hWnd, "GetDC failed!", NULL, MB_ICONSTOP); PostQuitMessage(0); return 0; } /* Setup Bitmap DC. */ if((hSurfaceDC = CreateCompatibleDC(hDC)) == NULL) { MessageBox(hWnd, "CreateCompatibleDC failed!", NULL, MB_ICONSTOP); PostQuitMessage(0); return 0; } /* Setup Bitmap it self. */ if((hSurface = CreateCompatibleBitmap(hDC, 640, 480)) == NULL) { MessageBox(hWnd, "CreateCompatibleBitmap failed!", NULL, MB_ICONSTOP); PostQuitMessage(0); return 0; } /* Connect Bitmap DC to Bitmap. */ if(SelectObject(hSurfaceDC, hSurface) == NULL) { MessageBox(hWnd, "SelectObject failed!", NULL, MB_ICONSTOP); PostQuitMessage(0); return 0; } /* Clear Bitmap. */ SelectObject(hSurfaceDC, GetStockObject(WHITE_BRUSH)); FloodFill(hSurfaceDC, 0, 0, RGB(255, 255, 255)); /* Create drawing pen. */ if((hPen = CreatePen(PS_SOLID, 30, RGB(255, 0, 0))) == NULL) { MessageBox(NULL, "CreatePen failed!", NULL, MB_ICONSTOP); PostQuitMessage(0); } return 0; case WM_DESTROY: /* Clean up! */ ReleaseDC(hWnd, hDC); DeleteDC(hSurfaceDC); DeleteObject(hSurface); /* Signal GetMessage to exit .. */ PostQuitMessage(0); return 0; case WM_PAINT: if((hDC = BeginPaint(hWnd, &PS)) != NULL) { /* Blit Bitmap DC onto window DC. */ if(!BitBlt(hDC, 0, 0, 640, 480, hSurfaceDC, 0, 0, SRCCOPY)) { MessageBox(hWnd, "BitBlt failed!", NULL, MB_ICONSTOP); PostQuitMessage(0); } EndPaint(hWnd, &PS); } return 0; case WM_MOUSEMOVE: if(wParam == MK_LBUTTON) { /* Draw on Bitmap surface. */ Pos.x = LOWORD(lParam); Pos.y = HIWORD(lParam); hPenBak = SelectObject(hSurfaceDC, hPen); MoveToEx(hSurfaceDC, Pos.x, Pos.y, NULL); LineTo(hSurfaceDC, Pos.x, Pos.y); SelectObject(hSurfaceDC, hPenBak); /* Signal window to update. */ InvalidateRect(hWnd, NULL, FALSE); break; } return 0; case WM_LBUTTONDOWN: /* Draw on mouse click instantly. */ GetCursorPos(&POS); ScreenToClient(hWnd, &POS); SendMessage(hWnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(POS.x, POS.y)); return 0; case WM_RBUTTONDOWN: /* Clear surface. */ SetRect(&rcClient, 0, 0, 640, 480); FillRect(hSurfaceDC, &rcClient, GetStockObject(WHITE_BRUSH)); /* Signal window to update. */ InvalidateRect(hWnd, NULL, FALSE); return 0; } return DefWindowProc(hWnd, Msg, wParam, lParam); }
Evgenios1 Δημοσ. 20 Ιανουαρίου 2010 Μέλος Δημοσ. 20 Ιανουαρίου 2010 [/color]Ένα κομάτι απο κώδικα που χρησιμοποιώ για ζωγράφισμα εκτός wm_paint. > int mdisplay::__GetDC(){ register HDC hdc = GetDC((HWND)owner()->getHwnd()); massert(((HDC)(mword)hdc) == hdc);//check for data loss set_hdc((mword)hdc); return hdc ? TRUE : FALSE; } void mdisplay::__ReleaseDC(){ if(hdc()){ int bReleased = ReleaseDC((HWND)owner()->getHwnd(),(HDC)hdc()); #ifdef _DEBUG //if(_u_winapi_getFlag("ReleaseDCLog",FALSE)){ // writeDebug( // "ReleaseDC(owner=%x, hdc=%x, returned %s)\n", // (mword)owner()->getHwnd(), // (mword)hdc(), // bReleased ? "RELEASES" : "NOT RELEASED" // ); //} #endif set_hdc(NULL); } } Αυτές είναι οι low level συναρτησεις του class που χρησιμοποιώ σε windows. Θα βγάλεις άκρη πιστευώ, εχω κρατήσει και τα "ονόματα" των windows (hdc,hwnd...) στα εσωτερικά members Θεος, τωρα το ειδα. > case WM_MOUSEMOVE: { if(wParam == MK_LBUTTON) { hdc = GetDC(hWnd); assert(hdc!=NULL); HPEN hPen = CreatePen(PS_SOLID,50,RGB(22,111,22)); SelectObject(hdc,hPen); assert(hPen != NULL); MoveToEx(hdc,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y,NULL); LineTo(hdc,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); ReleaseDC(hWnd,hdc); } } break;
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.