Hi, I have one problem about using BitBlt function.
I want to drag an image on client area by left mouse button down & mouse move, as like ACDSee.
My idea is as follows:
When Image.display.Dialog is created (= WM_INITDIALOG),
Image.Head.Coordinates(ImageHeadX, ImageHeadY) sets to 0.
Then, 'WM_PAINT' message Routine invokes 'BitBlt' function with normal 'Start' head.position.
Invoke BitBlt, hDC, 0, 0, imageWidth, imageHeight, hMemDC, ImageHeadX, ImageHeadY, SRCCOPY
is converted to
Invoke BitBlt, hDC, 0, 0, imageWidth, imageHeight, hMemDC, 0, 0, SRCCOPY
When left mouse button is down, (= WM_LBUTTONDOWN)
Stores current cusor position into CursorX1pos, CursorY1pos.
and then Mouse is moved, (= WM_MOUSEMOVE, MK_LBUTTON)
Gets current cusor position in CursorXpos, CursorYpos.
then,
Gets differents between them(= CursorX1pos - CursorXpos, CursorY1pos - CursorYpos )
and stores it(Results) into ImageHeadX, ImageHeadY
and sets 'MoveImageFlag'.
When left mouse button is up, (= WM_LBUTTONUP)
Sends 'WM_PAINT' message to Image display Window(hWnd).
Then, 'WM_PAINT' message Routine invokes 'BitBlt' function
with variable Image.Head.Coordinates(ImageHeadX, ImageHeadY).
Invoke BitBlt, hDC, 0, 0, imageWidth, imageHeight, hMemDC, ImageHeadX, ImageHeadY, SRCCOPY
But, these routine does not working.
I don't know How&Why.
Teach me, please.
-Asm.Student-
Begin of procedure CreateImageDialogProc
;;ready for display Dialog.Icon
;;=Invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, 32
Make global buffer memory with size 32, GMEM_FIXED+GMEM_ZEROINIT
Mov lpGlobalMemory, EAX
Push hIcon
;;=Pop lpGlobalMemory
Pop [EAX]
;;gets Screen width & Height
Invoke GetSystemMetrics, SM_CXSCREEN
Mov ScreenRect.right, EAX
Invoke GetSystemMetrics, SM_CYSCREEN
Mov ScreenRect.bottom, EAX
Mov EAX, imageHeight
Add EAX, 32
Mov EBX, imageWidth
Add EBX, 10
Style1 = WS_THICKFRAME+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE
Set dialog template "ImageViewer ver0.0.0", "MS Sans Serif", 10, Style1, \
0, \ ;;sets number of Controls(Button,Static,Icon, etc) in DialogBox
0,0,100,50, \ ;;sets default size of DialogBox
1024
Call modal dialog hInstance, 0, OperateImageDialogProc, ADDR lpGlobalMemory
Remove global buffer memory lpGlobalMemory
Ret
End of procedure CreateImageDialogProc
Data block
Set null dword CursorX1pos
Set null dword CursorY1pos
Set null dword CursorXpos
Set null dword CursorYpos
Set null dword ImageHeadX
Set null dword ImageHeadY
Set null byte MoveImageFlag
End block
Begin of procedure OperateImageDialogProc, <hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM>
.IF uMsg is WM_INITDIALOG
;; Displays DialogBox Icon
Mov EAX, lParam
Mov EAX, [EAX]
Invoke SendMessage, hWnd, WM_SETICON, 1, [EAX]
;; changes Frame.Size of DialogBox as Image Size
;
Mov EBX, imageWidth
;;adds as Left.Right.Frame.Boarder thickness
Add EBX, 8
.IF EBX > ScreenRect.right
Mov EBX, ScreenRect.right
.ENDIF
Mov EAX, imageHeight
;;adds as Caption & Bottom.Boarder thickness
Add EAX, 27
.IF EAX > ScreenRect.bottom
Mov EAX, ScreenRect.bottom
.ENDIF
Change window position and size with hWnd, 0, 0, EBX, EAX
Change window title hWnd, ADDR ImageFileNameBuffer
Mov ImageHeadX, 0
Mov ImageHeadY, 0
;;then flow jump to Routine for WM_PAINT
.ELSEIF uMsg is WM_LBUTTONUP
.IF MoveImageFlag is 1
Send message to hWnd, WM_PAINT
.ENDIF
.ELSEIF uMsg is WM_LBUTTONDOWN
.IF wParam is MK_LBUTTON
;;= Get high and low order word into EAX EBX from lParam
Mov EAX, lParam
Clear EBX
;;Get low order word into EBX
Mov BX, AX
;;Get high order word into EAX
Shr EAX, 16
Mov CursorX1pos, EBX
Mov CursorY1pos, EAX
.ENDIF
.ELSEIF uMsg is WM_MOUSEMOVE
.IF wParam is MK_LBUTTON
;;if Mouse moves during Left.Mouse.Button is down
;; displays specified bitmap image with changed position.
;
;; xPos = LOWORD(lParam); // horizontal position of cursor
;; yPos = HIWORD(lParam); // vertical position of cursor
;
;;= Get high and low order word into EAX EBX from lParam
Mov EAX, lParam
Clear EBX
;;Gets low order word into EBX
Mov BX, AX
;;Gets high order word into EAX
Shr EAX, 16
Mov CursorXpos, EBX
Mov CursorYpos, EAX
Mov EAX, CursorX1pos
.IF EAX > CursorXpos
Sub EAX, CursorXpos
Mov ImageHeadX, EAX
Mov MoveImageFlag, 1
.ENDIF
Mov EAX, CursorY1pos
.IF EAX > CursorYpos
Sub EAX, CursorYpos
Mov ImageHeadY, EAX
Mov MoveImageFlag, 1
.ENDIF
.ENDIF
.ELSEIF uMsg is WM_PAINT
Invoke BeginPaint, hWnd, ADDR PaintStruc
Mov hDC, EAX
;;creates Memory.DC which used by DC and gets Memory.DC handle
Invoke CreateCompatibleDC, hDC
Mov hMemDC, EAX
;; stores Bitmap into memory_DC
Invoke SelectObject, hMemDC, hBitmap
;; displays specified bitmap image
Invoke BitBlt, hDC, 0, 0, imageWidth, imageHeight, hMemDC, ImageHeadX, ImageHeadY, SRCCOPY
.IF MoveImageFlag is 1
Mov MoveImageFlag, 0
Mov ImageHeadX, 0
Mov ImageHeadY, 0
.ENDIF
Invoke DeleteDC, hMemDC
Invoke EndPaint, hWnd, ADDR PaintStruc
.ELSEIF uMsg is WM_CLOSE
Invoke DeleteObject, hBitmap
Invoke EndDialog, hWnd, NULL
.ELSE
Mov EAX, FALSE
Ret
.ENDIF
Mov EAX, TRUE
Ret
End of procedure OperateImageDialogProc
In my test,
Image is normally moved to specified coordinates by this method (adds two test line as bellow).
Mov ImageHeadX, 20
Mov ImageHeadY, 20
Invoke BitBlt, hDC, 0, 0, imageWidth, imageHeight, hMemDC, ImageHeadX, ImageHeadY, SRCCOPY
I think,
it may be caused that the variable ImageHeadX and ImageHeadY is initialized by any reason.
it seems be effected by Window Message Loop.
but I don't know exactly, why?
vega,
I know very little about using graphics in that manner but, there is one thing I _do_ know; without the MessageLoop interaction the WM_PAINT message would never be sent after processing WM_INITDIALOG. So certainly something MUST be going on with it. I am curious about one thing; why are you using a dialog box. The automatic handling of messages used by dialogs IMO is not as workable as with a standard window. In both cases CreateWindow is used but it is not done in as controllable way as if you used a standard window. I have no idea if this is an issue but I do see this as a possible area that could cause concern.
Paul