I need to draw an arbitrary rectangle and implement its stretching, i.e. clicked on one side, moved the cursor, and side dragged it. I wrote the program, but it works only if the window with the picture is fully expanded, I know what the error is (inconsistency between the coordinates of the workspace and the screen), but I can’t fix it. Help me please.

program Win1; uses Windows, Messages; var WndClass: TWndClass; szAppName: PChar; WinHandle: HWnd; Msg: TMsg; Pen: HPen; x1,y1,x2,y2: Integer; b1,b2,b3,b4,i,k,k1,i1: Integer; a1:Integer=100; a2:Integer=100; a3:Integer=550; a4:Integer=300; function MyWndProc (hWnd: HWND; Msg: UINT; wParam:WPARAM; lParam: LPARAM) : LRESULT; stdcall; var ps: TPaintStruct; Context: HDC; Font: HFont; gpoint: tpoint; begin case Msg of WM_MOUSEMOVE : begin // Перемещаем левую сторону if k=1 then begin if (wParam= MK_LBUTTON) then begin Context := GetDC (hWnd) ; GetCursorPos(gpoint); x2 := gpoint.x; y2 := gpoint.y;SelectObject (Context, GetStockObject (WHITE_PEN)); if x1<a3 then Rectangle(Context, a1+b1-5, a2, a3, a4) else Rectangle(Context, a1+b1+5, a2, a3, a4); b1:=x2-x1; b2:=y2-y1; SelectObject (Context, GetStockObject (BLACK_PEN)) ; Rectangle(Context, a1+b1, a2, a3, a4); end; ReleaseDC (hWnd, context) ; result:= 0; end; .............. и.д. (правую, верхнюю, нижнюю) WM_PAINT: begin Context := BeginPaint(hWnd, ps); try SelectObject(Context, Pen); Rectangle(Context, a1, a2, a3, a4); finally EndPaint(hWnd, ps); Result := 0; end; end; WM_LBUTTONDOWN : // захватываем левую сторону begin SetCapture(hwnd); GetCursorPos(gpoint); x1 := gpoint.x; y1 := gpoint.y; if a2<a4 then begin if (x1>(a1-5)) and (x1<a1+5) and (y1>(a2+5)) and (y1<(a4-5)) then k:=1; end; //if x1= pt[0].x //then k:=1; if a2>a4 then begin if (x1>(a1-5)) and (x1<(a1+5)) and (y1<(a2-5)) and (y1>(a4+5)) then k:=1; end; (и.д. ............) WM_LBUTTONUP : begin ReleaseCapture(); k:=0; k1:=0; i:=0; i1:=0; if (x1>(a1-5)) and (x1<(a1+5)) and (y1>(a2+5)) and (y1<(a4-5)) or (x1>(a1-5)) and (x1<(a1+5)) and (y1<(a2-5)) and (y1>(a4+5)) then a1:=a1+b1; (.................) создаём окно........... 

    1 answer 1

    I am personally afraid of things like (x1 > a1 - 5) and (y1 < a2 - 5) , so I will describe the way I would solve this problem.


    You have some rectangle, which is defined by 4 parameters - x, y, width, height , and, obviously, there is an object (or just a set of variables) where these values ​​are stored.

    You need to understand which parameter to change depending on where the mouse button was clicked, to save this, you should use the analogue enum in Delphi :

     type TRectangleChangingDirection = (ChangingX, ChangingY, ChangingWidth, ChangingHeight); 

    Then the sequence of actions is obvious:

    • WM_LBUTTONDOWN: Determine which particular rectangle parameter will be changed and write this value into a variable of type TRectangleChangingDirection . Also, the initial position of the cursor, since it is from him that the change in the parameters of the rectangle will be counted, let's call this variable rectangleChangeStartCursorPosition .

    • WM_MOUSEMOVE: Get the vector cursorDifference = currentPosition - rectangleChangeStartCursorPosition . From it, depending on the variable parameter in the rectangle, take the x or y coordinate and add it to this most variable rectangle parameter. Depending on the desired behavior, you can, for example, put restrictions on what, say, a rectangle cannot have a negative width, etc. Write the modified value to the parameters of the rectangle.

    • WM_BUTTONUP: You do not need to do anything, because the changes have already been recorded in the parameters of the rectangle.

    • WM_PAINT: Draw a rectangle on the current saved parameters.


    If you, for example, want to allow the ability to undo changes to a rectangle (say, by pressing the ESC button) , then you need to create 2 sets of parameters (x, y, width, height) - before the start of the change and during the change and, depending on the user’s action, apply changes or, conversely, roll them back to their original state. It turns out such a trivial application of the Transaction Pattern with the corresponding rollback'ом .