Page 1 of 1

IconMaker Gadget

Posted: Thu Feb 14, 2008 7:25 pm
by localmotion34
CODE EDITED AND UPDATED WITH SOME FIXES ECT....

Here is something I have put together because I needed it for my app, and I got Iconconstructor from GiveawayOfTheDay, which has a similar gadget.

This is a very alpha version, bit it essentially allows a user to select a rectangle of an image, and generates a 32, 48.64, or 128 pixel icon.

The gadget is layed out with the main image and selection box, and to the right there are 4 other image gadgets that grab the rectangle selection of the image. The rectangle is forced to be a square, although you could change the code if you wanted to do otherwise.

Moving the selection rectangle works perfectly, although i cant seem to figure out how to keep the entire selection square inside the image gadget.

Sizing the selection square is a bit more tricky, and can be buggy. If ANYONE can help with working out the bugs, id appreciate it.

The gadget works by proessing the #wm_mousemove commands and #wm_lbuttondown and up. After the selection rectangle is drawn, it sends a message to itself called #image_Rect_change. This message prompts grabbing of the selection rectangle and scaling it down for the other image gadgets.

In theory, you could load any image, get the selection you want, and save 32, 48, 64, and 128 pixel icons. I haven't got that far yet, but this code can be very adaptable for those that want it. Any hints or bug fixes are more than welcome, they are needed--lol.

Code: Select all

#WM_MOUSEHOVER = $2A1
#WM_MOUSELEAVE = $2A3
#TME_HOVER = 1
#TME_LEAVE = 2

#Icon_Rect_Change=$456

Structure iconbox
  width.l
  height.l
  pbID.l ;PB gadget number
  pbimage.l ; this is the REAL image that we load or create
  TLrect.RECT ;location for the top left grab box
  TRrect.RECT  ;""
  BLrect.RECT;""
  BRrect.RECT;""
  LocRect.RECT  ;this is the actual rectangle of the selection box
  tempimage.l ;we dont want to mess up the real image, so we ALWAYS draw on this one
  image32.l ;32x32 image gadget
  image48.l;""
  image64.l;""
  image128.l;""
  PBimage32.l ;this is the image associated with the 32x32 - we just redraw over this to save memory and creating constant new images
  PBimage48.l ;""
  PBimage64.l;""
  PBimage128.l;""
EndStructure
Global*box.iconbox=AllocateMemory(SizeOf(iconbox))
Global mousedown.l,MouseBtnDownX,MouseBtnDownY,mousedowntopleft.l, mousedowntopright.l, mousedownbotleft.l,mousedownbotright.l, drawrect.RECT
Procedure.w LOWORD(Value.l) ;windef.h macro
  ProcedureReturn (Value & $FFFF)
EndProcedure

Procedure.w HIWORD(Value.l) ;windef.h macro
  ProcedureReturn ((Value >> 16) & $FFFF)
EndProcedure 

Procedure ScaleImage(hBitmap,width.l,height.l,color.l)
  Define.l OriW, OriH, w, h, oriAR, newAR
  Define.f fw, fh
  GetObject_(hBitmap,SizeOf(BITMAP),bz.BITMAP)
  OriW=bz\bmWidth
  OriH=bz\bmHeight
  tempimage=CreateImage(#PB_Any,bz\bmWidth,bz\bmHeight)
  hdc=StartDrawing(ImageOutput(tempimage))
  DrawImage(hBitmap,0,0)
  StopDrawing()
  
  If (OriH > OriW And height < width) Or (OriH < OriW And height > width)
    Swap width, height
  EndIf
  
  ; Calc Factor
  fw = width/OriW
  fh = height/OriH
  
  ; Calc AspectRatio
  oriAR = Round((OriW / OriH) * 10,0)
  newAR = Round((width / height) * 10,0)
  
  ; AspectRatio already correct?
  If oriAR = newAR
    w = width
    h = height
  ElseIf OriW * fh <= width
    w = OriW * fh
    h = OriH * fh
  ElseIf OriH * fw <= height
    w = OriW * fw
    h = OriH * fw 
  EndIf
  
  fixx=(width/2)-(w/2)
  fixy=(height/2)-(h/2) 
  ResizeImage(tempimage,w,h,#PB_Image_Smooth)
  newPhoto=CreateImage(#PB_Any,width,height)
  hdc=StartDrawing(ImageOutput(newPhoto))
  SelectObject_(newdc,hBitmap)
  Box(0,0,width,height,color)
  DrawImage(ImageID(tempimage), fixx,fixy)
  StopDrawing() 
  FreeImage(tempimage)
  ProcedureReturn newPhoto
EndProcedure 

Procedure DrawSelectRect(*rect.RECT,gadget,numberimage)
  *box.iconbox=GetWindowLong_(GadgetID(gadget),#GWL_USERDATA)
  If *box\tempimage
    FreeImage(*box\tempimage);get rid of it and start over
  EndIf 
  tempimage=CreateImage(#PB_Any,*box\width,*box\height)
  StartDrawing(ImageOutput(tempimage))
  DrawImage(ImageID(numberimage),0,0) ;draw the REAL image associated with the gadget
  DrawingMode(#PB_2DDrawing_Outlined)
  width=*rect\right-*rect\left 
  height=*rect\bottom-*rect\top
  Box(*rect\left,*rect\top,width,height, #Blue);actual selection box
  DrawingMode(#PB_2DDrawing_Default)
  LineXY(*rect\left+width/2,*rect\top,*rect\left+width/2,*rect\bottom,#Blue)
  LineXY(*rect\left,*rect\top+height/2,*rect\right,*rect\top+height/2,#Blue)
  Box(*rect\left-6,*rect\top-6,6,6,#Blue); Top Left
  Box(*rect\right,*rect\top-6,6,6,#Blue)  ;Top Right
  Box(*rect\left-6,*rect\bottom,6,6,#Blue) ;Bottom Left
  Box(*rect\right,*rect\bottom,6,6,#Blue);Bottom Left
  StopDrawing()
  SetGadgetState(gadget,ImageID(tempimage))
  
  With *box
    *box\TLrect\left=*rect\left-6
    *box\TLrect\top=*rect\top-6
    *box\TLrect\right=*rect\left
    *box\TLrect\bottom=*rect\top
    
    *box\TRrect\left=*rect\right
    *box\TRrect\top=*rect\top-6
    *box\TRrect\right=*rect\right+6
    *box\TRrect\bottom =*rect\top
    
    *box\BLrect\left=*rect\left-6
    *box\BLrect\top=*rect\bottom
    *box\BLrect\right=*rect\left
    *box\BLrect\bottom=*rect\bottom+6
    
    *box\BRrect\left=*rect\right
    *box\BRrect\top=*rect\bottom
    *box\BRrect\right=*rect\right+6
    *box\BRrect\bottom=*rect\bottom+6
    
    *box\LocRect\left=*rect\left
    *box\LocRect\right=*rect\right
    *box\LocRect\top=*rect\top
    *box\LocRect\bottom=*rect\bottom 
    
    *box\tempimage=tempimage 
  EndWith
  SetWindowLong_(GadgetID(gadget),#GWL_USERDATA,*box)
EndProcedure 

Procedure DrawRect(*rect.RECT,gadget,numberimage)
  *boxrect.iconbox=GetWindowLong_(GadgetID(gadget),#GWL_USERDATA)
  If *boxrect\tempimage
    FreeImage(*boxrect\tempimage)
  EndIf 
  tempimage=CreateImage(#PB_Any,*boxrect\width,*boxrect\height)
  StartDrawing(ImageOutput(tempimage))
  DrawImage(ImageID(numberimage),0,0)
  DrawingMode(#PB_2DDrawing_Outlined)
  width=*rect\right-*rect\left 
  height=*rect\bottom-*rect\top
  Box(*rect\left,*rect\top,width,height, #Blue)
  StopDrawing()
  SetGadgetState(gadget,ImageID(tempimage))
EndProcedure 

Procedure IconProc(hwnd,msg,wParam,lParam)
  Select msg
    Case #WM_KEYDOWN
      Select wParam
        Case #VK_UP
          Debug "up" 
        Case #VK_DOWN
          
      EndSelect 
    Case #WM_PAINT 
      
    Case #WM_LBUTTONDOWN
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      xPos = LOWORD(lParam)
      yPos = HIWORD(lParam)
      MouseBtnDownX=LOWORD(lParam)
      MouseBtnDownY=HIWORD(lParam)
      therect.RECT 
      With therect.RECT
        \left=*boxrect\LocRect\left
        \right=*boxrect\LocRect\right
        \top=*boxrect\LocRect\top
        \bottom=*boxrect\LocRect\bottom
      EndWith 
      If ptinrect_(therect.RECT,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_HAND)
        SetCursor_(hCurHand)
        SetCapture_(hwnd)
        getwindowrect_(hwnd,rect.RECT)
        ClipCursor_(rect.RECT)
        mousedown.l=1
      ElseIf ptinrect_(*boxrect\TLrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        mousedowntopleft.l=1
        getwindowrect_(hwnd,rect.RECT)
        ClipCursor_(rect.RECT)
      ElseIf ptinrect_(*boxrect\TRrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENESW	)
        SetCursor_(hCurHand)
        mousedowntopright=1
        getwindowrect_(hwnd,rect.RECT)
        ClipCursor_(rect.RECT)
      ElseIf ptinrect_(*boxrect\BLrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENESW	)
        SetCursor_(hCurHand)
        mousedownbotleft=1
        getwindowrect_(hwnd,rect.RECT)
        ClipCursor_(rect.RECT)
      ElseIf ptinrect_(*boxrect\BRrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        mousedownbotright=1
        getwindowrect_(hwnd,rect.RECT)
        ClipCursor_(rect.RECT)
      EndIf
      ProcedureReturn 0
    Case #WM_LBUTTONUP
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      ClipCursor_(#Null)
      If mousedowntopleft=1 Or mousedowntopright=1 Or mousedownbotleft=1 Or mousedownbotright=1
        DrawSelectRect(drawrect.RECT,*box\pbID,*box\pbimage)
        SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
      EndIf 
      mousedown.l=0
      mousedowntopleft=0
      mousedowntopright=0
      mousedownbotleft=0
      mousedownbotright=0
      ReleaseCapture_()
    Case #WM_RBUTTONDOWN
      
    Case #WM_RBUTTONUP
      
    Case #WM_MOUSEMOVE
      GetCursorPos_(point.POINT)
      screentoclient_(hwnd,point.POINT)
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      Structure myTRACKMOUSEEVENT
        cbSize.l
        dwFlags.l
        hwndTrack.l  
        dwHoverTime.l
      EndStructure
      mte.myTRACKMOUSEEVENT
      mte\cbSize = SizeOf(myTRACKMOUSEEVENT)
      mte\dwFlags = #TME_LEAVE
      mte\hwndTrack = hwnd
      TrackMouseEvent_(mte)
      xPos = LOWORD(lParam)
      yPos = HIWORD(lParam)
      therect.RECT 
      With therect.RECT
        \left=*boxrect\LocRect\left
        \right=*boxrect\LocRect\right
        \top=*boxrect\LocRect\top
        \bottom=*boxrect\LocRect\bottom
      EndWith 
      If ptinrect_(therect.RECT,xPos,yPos) And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_HAND)
        SetCursor_(hCurHand)
        If mousedown=1
          MouseOffsetX.w = lParam&$FFFF       - MouseBtnDownX 
          MouseOffsetY.w = (lParam>>16) - MouseBtnDownY 
          drawrect.RECT
          With drawrect
            \left=*boxrect\LocRect\left+MouseOffsetX
            \right=*boxrect\LocRect\right+MouseOffsetX
            \top=*boxrect\LocRect\top+MouseOffsetY
            \bottom=*boxrect\LocRect\bottom+MouseOffsetY
            
            If \left < 0
              \left = 0
              \right = *boxrect\LocRect\right - *boxrect\LocRect\left
            ElseIf \right >= ImageWidth(*boxrect\pbimage)
              \right = ImageWidth(*boxrect\pbimage) - 1
              \left = \right - (*boxrect\LocRect\right - *boxrect\LocRect\left)
            EndIf
            
            If \top < 0
              \top = 0
              \bottom = *boxrect\LocRect\bottom - *boxrect\LocRect\top
            ElseIf \bottom >= ImageHeight(*boxrect\pbimage)
              \bottom = ImageHeight(*boxrect\pbimage) - 1
              \top = \bottom - (*boxrect\LocRect\bottom - *boxrect\LocRect\top)
            EndIf
          EndWith
          DrawSelectRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage)
          SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
          MouseBtnDownX + MouseOffsetX 
          MouseBtnDownY + MouseOffsetY 
        EndIf 
      ElseIf ptinrect_(*boxrect\TLrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0 And mousedown=0
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
      ElseIf ptinrect_(*boxrect\TRrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0 And mousedown=0
        hCurHand = LoadCursor_(0,#IDC_SIZENESW	)
        SetCursor_(hCurHand)
      ElseIf ptinrect_(*boxrect\BLrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0 And mousedown=0
        hCurHand = LoadCursor_(0,#IDC_SIZENESW	)
        SetCursor_(hCurHand)
      ElseIf ptinrect_(*boxrect\BRrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0 And mousedown=0
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
      EndIf
      If mousedowntopleft=1   ;Keep in mine here that we want a SQUARE, so the greatest change in movement is forced to be accepted for both X and Y
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF       - MouseBtnDownX 
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY 
        drawrect.RECT
        If Abs(MouseOffsetX)<Abs(MouseOffsetY)
          Xaddition.l=MouseOffsetY
          Yaddition=MouseOffsetY
        ElseIf Abs(MouseOffsetX)>Abs(MouseOffsetY)
          Xaddition.l=MouseOffsetX
          Yaddition=MouseOffsetX
        ElseIf Abs(MouseOffsetX)=Abs(MouseOffsetY)
          Xaddition=MouseOffsetX
          Yaddition=MouseOffsetY
        EndIf 
        With drawrect
          \left=*boxrect\LocRect\left+Xaddition
          \right=*boxrect\LocRect\right
          \top=*boxrect\LocRect\top+Yaddition
          \bottom=*boxrect\LocRect\bottom
        EndWith 
        If drawrect\right-drawrect\left >=32
          DrawRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage) 
        Else
          With drawrect
            \left=*boxrect\LocRect\right-32
            \right=*boxrect\LocRect\right
            \top=*boxrect\LocRect\bottom-32
            \bottom=*boxrect\LocRect\bottom
          EndWith 
          DrawRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage) 
        EndIf 
      ElseIf mousedowntopright=1
        hCurHand = LoadCursor_(0,#IDC_SIZENESW)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF       - MouseBtnDownX 
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY 
        drawrect.RECT
        If Abs(MouseOffsetX)<Abs(MouseOffsetY) ; greater change in Y movement
          If MouseOffsetY<0
            Xaddition.l=Abs(MouseOffsetY)
            Yaddition=MouseOffsetY
          ElseIf MouseOffsetY>0
            Xaddition.l=-MouseOffsetY
            Yaddition=MouseOffsetY
          EndIf 
        ElseIf Abs(MouseOffsetX)>Abs(MouseOffsetY) ;greater change in X movement
          If MouseOffsetX<0
            Xaddition.l=MouseOffsetX
            Yaddition=-MouseOffsetX
          ElseIf MouseOffsetX>0
            Xaddition.l=MouseOffsetX
            Yaddition=-MouseOffsetX
          EndIf 
          
        ElseIf Abs(MouseOffsetX)=Abs(MouseOffsetY)
          Xaddition=MouseOffsetX
          Yaddition=MouseOffsetY
        EndIf 
        With drawrect
          \left=*boxrect\LocRect\left
          \right=*boxrect\LocRect\right+Xaddition.l
          \top=*boxrect\LocRect\top+Yaddition.l
          \bottom=*boxrect\LocRect\bottom
        EndWith 
        If drawrect\right-drawrect\left >=32
          DrawRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage) 
        Else
          With drawrect
            \left=*boxrect\LocRect\left
            \right=*boxrect\LocRect\left+32
            \top=*boxrect\LocRect\bottom-32
            \bottom=*boxrect\LocRect\bottom
          EndWith 
          DrawRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage) 
        EndIf 
      ElseIf mousedownbotleft=1
        hCurHand = LoadCursor_(0,#IDC_SIZENESW)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF       - MouseBtnDownX 
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY 
        drawrect.RECT
        If Abs(MouseOffsetX)<Abs(MouseOffsetY) ; greater change in Y movement
          If MouseOffsetY<0
            Xaddition.l=-MouseOffsetY
            Yaddition=MouseOffsetY
          ElseIf MouseOffsetY>0
            Xaddition.l=-MouseOffsetY
            Yaddition=MouseOffsetY
          EndIf 
        ElseIf Abs(MouseOffsetX)>Abs(MouseOffsetY) ;greater change in X movement
          If MouseOffsetX<0
            Xaddition.l=MouseOffsetX
            Yaddition=-MouseOffsetX
          ElseIf MouseOffsetX>0
            Xaddition.l=MouseOffsetX
            Yaddition=-MouseOffsetX
          EndIf 
          
        ElseIf Abs(MouseOffsetX)=Abs(MouseOffsetY)
          Xaddition=MouseOffsetX
          Yaddition=MouseOffsetY
        EndIf 
        With drawrect
          \left=*boxrect\LocRect\left+Xaddition.l
          \right=*boxrect\LocRect\right
          \top=*boxrect\LocRect\top
          \bottom=*boxrect\LocRect\bottom+Yaddition.l
        EndWith 
        If drawrect\right-drawrect\left >=32
          DrawRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage) 
        Else
          With drawrect
            \left=*boxrect\LocRect\right-32
            \right=*boxrect\LocRect\right
            \top=*boxrect\LocRect\top
            \bottom=*boxrect\LocRect\top+32
          EndWith 
          DrawRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage) 
        EndIf 
      ElseIf mousedownbotright=1
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF       - MouseBtnDownX 
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY 
        drawrect.RECT
        If Abs(MouseOffsetX)<Abs(MouseOffsetY) ; greater change in Y movement
          If MouseOffsetY<0
            Xaddition.l=MouseOffsetY
            Yaddition=MouseOffsetY
          ElseIf MouseOffsetY>0
            Xaddition.l=MouseOffsetY
            Yaddition=MouseOffsetY
          EndIf 
        ElseIf Abs(MouseOffsetX)>Abs(MouseOffsetY) ;greater change in X movement
          If MouseOffsetX<0
            Xaddition.l=MouseOffsetX
            Yaddition=MouseOffsetX
          ElseIf MouseOffsetX>0
            Xaddition.l=MouseOffsetX
            Yaddition=MouseOffsetX
          EndIf 
          
        ElseIf Abs(MouseOffsetX)=Abs(MouseOffsetY)
          Xaddition=MouseOffsetX
          Yaddition=MouseOffsetY
        EndIf 
        With drawrect
          \left=*boxrect\LocRect\left
          \right=*boxrect\LocRect\right+Xaddition.l
          \top=*boxrect\LocRect\top
          \bottom=*boxrect\LocRect\bottom+Yaddition.l
        EndWith 
        If drawrect\right-drawrect\left >=32
          DrawRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage) 
        Else
          With drawrect
            \left=*boxrect\LocRect\left
            \right=*boxrect\LocRect\left+32
            \top=*boxrect\LocRect\top
            \bottom=*boxrect\LocRect\top+32
          EndWith 
          DrawRect(drawrect.RECT,*boxrect\pbID,*boxrect\pbimage) 
        EndIf 
      EndIf 
      
      
      ProcedureReturn 0
    Case #WM_MOUSEHOVER 
      
    Case #WM_MOUSELEAVE
      
    Case #Icon_Rect_Change
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      Resultimage = GrabImage(*boxrect\pbimage, #PB_Any, *boxrect\LocRect\left, *boxrect\LocRect\top, *boxrect\LocRect\right-*boxrect\LocRect\left, *boxrect\LocRect\bottom-*boxrect\LocRect\top)
      StartDrawing(ImageOutput(*boxrect\PBimage32))
      DrawImage(ImageID(Resultimage),0,0,32,32)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage48))
      DrawImage(ImageID(Resultimage),0,0,48,48)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage64))
      DrawImage(ImageID(Resultimage),0,0,64,64)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage128))
      DrawImage(ImageID(Resultimage),0,0,128,128)
      StopDrawing()
      SetGadgetState(*boxrect\image32,ImageID(*boxrect\PBimage32))
      SetGadgetState(*boxrect\image48,ImageID(*boxrect\PBimage48))
      SetGadgetState(*boxrect\image64,ImageID(*boxrect\PBimage64))
      SetGadgetState(*boxrect\image128,ImageID(*boxrect\PBimage128))
      FreeImage(Resultimage)
  EndSelect 
  ProcedureReturn CallWindowProc_(GetProp_(hwnd,"oldproc"),hwnd,msg,wParam,lParam)
EndProcedure 

Procedure IconGadget(id.l,x,y,width,height)
  image=CreateImage(#PB_Any,width,height)
  StartDrawing(ImageOutput(image))
  Box(0,0,400,300,#White)
  Circle(200,150,60,#Red)
  StopDrawing()
  container=ContainerGadget(#PB_Any,x,y,width+154,height+20,#PB_Container_Raised)
  imagegad.l=ImageGadget(id,5,5,width,height,ImageID(image),#PB_Image_Border)
  PBimage32.l=CreateImage(#PB_Any,32,32)
  PBimage48.l=CreateImage(#PB_Any,48,48)
  PBimage64.l=CreateImage(#PB_Any,64,64)
  PBimage128.l=CreateImage(#PB_Any,128,128)
  image32.l=ImageGadget(#PB_Any,width+64,10,32,32,ImageID(PBimage32),#PB_Image_Border)
  image48.l=ImageGadget(#PB_Any,width+56,50,48,48,ImageID(PBimage48),#PB_Image_Border)
  image64.l=ImageGadget(#PB_Any,width+46,107,64,64,ImageID(PBimage64),#PB_Image_Border)
  image128.l=ImageGadget(#PB_Any,width+14,180,128,128,ImageID(PBimage128),#PB_Image_Border)
  CloseGadgetList()
  rect.RECT
  rect\left=width/2-50
  rect\right=width/2 +50
  rect\top=height/2-50
  rect\bottom=height/2+50
  If id=#PB_Any
    *box\pbID=imagegad
    hwndreturn=imagegad
    hwnd=GadgetID(imagegad)
  Else
    *box\pbID=id
    hwndreturn=imagegad
    hwnd=imagegad
  EndIf 
  *box\width=width
  *box\height=height
  *box\pbimage=image
  *box\image32=image32
  *box\image48=image48
  *box\image64=image64
  *box\image128=image128
  *box\PBimage32=PBimage32
  *box\PBimage48=PBimage48
  *box\PBimage64=PBimage64
  *box\PBimage128=PBimage128
  SetWindowLong_(hwnd,#GWL_USERDATA,*box)
  SetProp_(hwnd,"oldproc",SetWindowLong_(hwnd,#GWL_WNDPROC,@IconProc()))
  DrawSelectRect(rect.RECT,*box\pbID,image)
  SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
  
EndProcedure 

Procedure SetIconGadgetImage(icongadget,PBimageNumber)
  
  *boxrect.iconbox=GetWindowLong_(GadgetID(icongadget),#GWL_USERDATA)
  Debug GadgetWidth(*boxrect\pbID)
  newimage.l=ScaleImage(ImageID(PBimageNumber),*box\width,*box\height,#White)
  ResizeImage(newimage,*box\width,*box\height)
  tempimage=CopyImage(newimage,#PB_Any)
  If IsImage(*boxrect\pbimage)
    FreeImage(*boxrect\pbimage)
  EndIf 
  If IsImage(*boxrect\tempimage)
    FreeImage(*boxrect\tempimage)
  EndIf 
  Debug GadgetWidth(*boxrect\pbID)
  *boxrect\pbimage=newimage
  *boxrect\tempimage=tempimage
  SetGadgetState(icongadget,ImageID(newimage))
  SetWindowLong_(GadgetID(icongadget),#GWL_USERDATA,*boxrect)
  rect.RECT
  rect\left=GadgetWidth(*boxrect\pbID)/2-50
  rect\right=GadgetWidth(*boxrect\pbID)/2 +50
  rect\top=GadgetHeight(*boxrect\pbID)/2-50
  rect\bottom=GadgetHeight(*boxrect\pbID)/2+50
  DrawSelectRect(rect.RECT,*boxrect\pbID,newimage)
  Debug GadgetWidth(*boxrect\pbID)
  FreeImage(PBimageNumber)
  SendMessage_(GadgetID(*boxrect\pbID),#Icon_Rect_Change, drawrect.RECT,0)
  Debug  GadgetWidth(*boxrect\pbID)
EndProcedure 
  
UseJPEGImageDecoder()
UsePNGImageDecoder()

If OpenWindow(0, 259, 217, 605, 388, "IconMaker Gadget",  #PB_Window_SystemMenu |  #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  
  
  If CreateGadgetList(WindowID(0))
    IconGadget(10,20,40,400,300)
    ButtonGadget(1,30,10,70,20,"Open Image")
  EndIf
EndIf


;-Event Loop 
Repeat 
  Select WaitWindowEvent()
    
    Case #PB_Event_Gadget
      Select EventGadget()
        
        Case 1
          imagefile$=OpenFileRequester("Open An Image","","Images|*.bmp;*.jpg;*.png",0)
          If imagefile$
            image=LoadImage(#PB_Any,imagefile$)
            SetIconGadgetImage(10,image)
          EndIf 
      EndSelect
    Case #PB_Event_Menu
      Select EventMenu()
        
      EndSelect 
    Case #PB_Event_CloseWindow
      Quit=1
  EndSelect
Until Quit=1 

Posted: Thu Feb 14, 2008 9:24 pm
by akj
@localmotion34

I would like to suggest two additional control features:

1. When one of the 4 blue corner nodes has been selected, it (or it's centre) should change to another colour (say black) and this selected node should then be capable of being nudged by the arrow keys (up, down, left, right), one pixel per keypress. This would make precise control very easy.

2. It would be useful to have a set of crosshairs (+) within the control square to locate the the centres of the edges and centre of the square. The user would probably need to be able to toggle this feature on and off.

Posted: Thu Feb 14, 2008 10:49 pm
by r_hyde
Replace lines 203-208 with the code below for a start on keeping the selection gizmo inside the boundary. This also prevents an insidious crash bug when trying to drag it where it shouldn't go!

Code: Select all

With drawrect 
  \left=*boxrect\LocRect\left+MouseOffsetX 
  \right=*boxrect\LocRect\right+MouseOffsetX 
  \top=*boxrect\LocRect\top+MouseOffsetY 
  \bottom=*boxrect\LocRect\bottom+MouseOffsetY
  
  If \left < 0
    \left = 0
    \right = *boxrect\LocRect\right - *boxrect\LocRect\left
  ElseIf \right >= ImageWidth(*boxrect\pbimage)
    \right = ImageWidth(*boxrect\pbimage) - 1
    \left = \right - (*boxrect\LocRect\right - *boxrect\LocRect\left)
  EndIf
  
  If \top < 0
    \top = 0
    \bottom = *boxrect\LocRect\bottom - *boxrect\LocRect\top
  ElseIf \bottom >= ImageHeight(*boxrect\pbimage)
    \bottom = ImageHeight(*boxrect\pbimage) - 1
    \top = \bottom - (*boxrect\LocRect\bottom - *boxrect\LocRect\top)
  EndIf
EndWith
Edit: forgot to mention that this is a very nifty little control :)

Posted: Fri Feb 15, 2008 6:08 am
by localmotion34
r_hyde wrote:Replace lines 203-208 with the code below for a start on keeping the selection gizmo inside the boundary. This also prevents an insidious crash bug when trying to drag it where it shouldn't go!

Edit: forgot to mention that this is a very nifty little control :)
Thanks for the code fix! I just gave up on how to do that. I first tried coding every possible permutation of every selection box and the change in X and Y values, but %$%$%$ that.

----As for the keyboard arrows moving the selection box, the MSDN says Static controls don't receive the keyboard focus. Id prefer to keep ALL processing in the callback window procedure, so how does one make the keyboard thing work?

Posted: Fri Feb 15, 2008 7:01 am
by Dare
Looks pretty cool. :)

Posted: Sat Feb 16, 2008 8:33 pm
by akj
@localmotion34

In the code below I have implemented the two features I suggested of highlighting the selected corner of the box and nudging the box with the cursor keys.

Non-trivial changes have been identified by a comment of 'AKJ'.

I think I have detected a bug in the new routine ScaleImage() and I have identified the line.

Also, there appears to be bugs in IconGadget(), also identified.

My main improvement is that I have greatly simplified the logic for resizing the selection box. The revised coding is in the new routine NudgeNode(). The new version of the complete program is about 60 lines shorter, even with the extra features.

I have introduced a new global variable called 'node' and this could be used more than it is to simplify the logic involving variables like 'mousedowntopleft' and may eventually result in their complete elimination.

I have also applied EnableExplicit to the program.

Code: Select all

; IconMaker Gadget  16-Feb-08
; By localmotion34
; www.purebasic.fr/english/viewtopic.php?t=31133

EnableExplicit ; AKJ

#WM_MOUSEHOVER = $2A1
#WM_MOUSELEAVE = $2A3
#TME_HOVER = 1
#TME_LEAVE = 2

#Icon_Rect_Change=$456

Structure iconbox
  width.l
  height.l
  pbID.l ;PB gadget number
  pbimage.l ; this is the REAL image that we load or create
  TLrect.RECT ;location for the top left grab box
  TRrect.RECT  ;""
  BLrect.RECT ;""
  BRrect.RECT ;""
  LocRect.RECT  ;this is the actual rectangle of the selection box
  tempimage.l ;we dont want to mess up the real image, so we ALWAYS draw on this one
  image32.l ;32x32 image gadget
  image48.l ;""
  image64.l ;""
  image128.l ;""
  PBimage32.l ;this is the image associated with the 32x32 - we just redraw over this to save memory and creating constant new images
  PBimage48.l ;""
  PBimage64.l ;""
  PBimage128.l ;""
EndStructure

Structure myTRACKMOUSEEVENT ; AKJ
  cbSize.l
  dwFlags.l
  hwndTrack.l
  dwHoverTime.l
EndStructure

Global*box.iconbox=AllocateMemory(SizeOf(iconbox))
Global mousedown.l,MouseBtnDownX,MouseBtnDownY,mousedowntopleft.l, mousedowntopright.l, mousedownbotleft.l,mousedownbotright.l, drawrect.RECT
Global node.l=0 ; AKJ Selected node (corner)  0=none  1=topleft  2=topright  3=botleft  4=botright

Procedure.w LOWORD(Value.l) ;windef.h macro
  ProcedureReturn (Value & $FFFF)
EndProcedure

Procedure.w HIWORD(Value.l) ;windef.h macro
  ProcedureReturn ((Value >> 16) & $FFFF)
EndProcedure

Procedure.l ScaleImage(hBitmap,width.l,height.l,color.l)
  Protected OriW, OriH, w, h, oriAR, newAR ; AKJ
  Protected fw.d, fh.d ; AKJ
  Protected tempimage, hdc, fixx, fixy, newPhoto, newdc, bz.BITMAP ; AKJ
  GetObject_(hBitmap,SizeOf(BITMAP),bz)
  OriW=bz\bmWidth
  OriH=bz\bmHeight
  tempimage=CreateImage(#PB_Any,bz\bmWidth,bz\bmHeight)
  hdc=StartDrawing(ImageOutput(tempimage))
  DrawImage(hBitmap,0,0)
  StopDrawing()

  If (OriH > OriW And height < width) Or (OriH < OriW And height > width)
    Swap width, height
  EndIf

  ; Calc Factor
  fw = width/OriW
  fh = height/OriH

  ; Calc AspectRatio
  oriAR = Round((OriW / OriH) * 10,0)
  newAR = Round((width / height) * 10,0)

  ; AspectRatio already correct?
  If oriAR = newAR
    w = width
    h = height
  ElseIf OriW * fh <= width
    w = OriW * fh
    h = OriH * fh
  ElseIf OriH * fw <= height
    w = OriW * fw
    h = OriH * fw
  EndIf

  fixx=(width/2)-(w/2)
  fixy=(height/2)-(h/2)
  ResizeImage(tempimage,w,h,#PB_Image_Smooth)
  newPhoto=CreateImage(#PB_Any,width,height)
  newdc=StartDrawing(ImageOutput(newPhoto)) ; AKJ was hdc - Bug?
  SelectObject_(newdc,hBitmap)
  Box(0,0,width,height,color)
  DrawImage(ImageID(tempimage), fixx,fixy)
  StopDrawing()
  FreeImage(tempimage)
  ProcedureReturn newPhoto
EndProcedure

Procedure DrawSelectRect(*rect.RECT,gadget,numberimage)
; Draw selection rectangle and nodes
  Protected *box.iconbox, width, height, tempimage, colour ; AKJ
  *box=GetWindowLong_(GadgetID(gadget),#GWL_USERDATA)
  If *box\tempimage
    FreeImage(*box\tempimage);get rid of it and start over
  EndIf
  tempimage=CreateImage(#PB_Any,*box\width, *box\height)
  StartDrawing(ImageOutput(tempimage))
  DrawImage(ImageID(numberimage),0,0) ;draw the REAL image associated with the gadget
  DrawingMode(#PB_2DDrawing_Outlined)
  width=*rect\right-*rect\left
  height=*rect\bottom-*rect\top
  Box(*rect\left,*rect\top,width,height, #Blue);actual selection box
  DrawingMode(#PB_2DDrawing_Default)
  LineXY(*rect\left+width/2,*rect\top,*rect\left+width/2,*rect\bottom,#Blue)
  LineXY(*rect\left,*rect\top+height/2,*rect\right,*rect\top+height/2,#Blue)
  Box(*rect\left-6,*rect\top-6,6,6,#Blue); Top Left
  Box(*rect\right,*rect\top-6,6,6,#Blue)  ;Top Right
  Box(*rect\left-6,*rect\bottom,6,6,#Blue) ;Bottom Left
  Box(*rect\right,*rect\bottom,6,6,#Blue) ;Bottom Left
  ; AKJ Highlight the selected corner node of the box
  colour = #Yellow
  Select node
    Case 1: Box(*rect\left-5,*rect\top-5,4,4,colour)
    Case 2: Box(*rect\right+1,*rect\top-5,4,4,colour)
    Case 3: Box(*rect\left-5,*rect\bottom+1,4,4,colour)
    Case 4: Box(*rect\right+1,*rect\bottom+1,4,4,colour)
  EndSelect
  StopDrawing()
  SetGadgetState(gadget,ImageID(tempimage))

  With *box
    *box\TLrect\left=*rect\left-6
    *box\TLrect\top=*rect\top-6
    *box\TLrect\right=*rect\left
    *box\TLrect\bottom=*rect\top

    *box\TRrect\left=*rect\right
    *box\TRrect\top=*rect\top-6
    *box\TRrect\right=*rect\right+6
    *box\TRrect\bottom =*rect\top

    *box\BLrect\left=*rect\left-6
    *box\BLrect\top=*rect\bottom
    *box\BLrect\right=*rect\left
    *box\BLrect\bottom=*rect\bottom+6

    *box\BRrect\left=*rect\right
    *box\BRrect\top=*rect\bottom
    *box\BRrect\right=*rect\right+6
    *box\BRrect\bottom=*rect\bottom+6

    *box\LocRect\left=*rect\left
    *box\LocRect\right=*rect\right
    *box\LocRect\top=*rect\top
    *box\LocRect\bottom=*rect\bottom

    *box\tempimage=tempimage
  EndWith
  SetWindowLong_(GadgetID(gadget),#GWL_USERDATA,*box)
EndProcedure

Procedure DrawRect(*rect.RECT,gadget,numberimage)
; Draw rectangle (without nodes)
  Protected *boxrect.iconbox, tempimage, width, height ; AKJ
  *boxrect=GetWindowLong_(GadgetID(gadget),#GWL_USERDATA)
  If *boxrect\tempimage
    FreeImage(*boxrect\tempimage)
  EndIf
  tempimage=CreateImage(#PB_Any, *boxrect\width, *boxrect\height)
  StartDrawing(ImageOutput(tempimage))
  DrawImage(ImageID(numberimage),0,0)
  DrawingMode(#PB_2DDrawing_Outlined)
  width=*rect\right-*rect\left
  height=*rect\bottom-*rect\top
  Box(*rect\left,*rect\top,width,height, #Blue)
  StopDrawing()
  SetGadgetState(gadget,ImageID(tempimage))
EndProcedure

Procedure NudgeRect(hwnd, dx, dy) ; AKJ
; Move the selection rectangle by a given offset
; This code is replicated from the #WM_MOUSEMOVE case of IconProc()
Protected *boxrect.iconbox
  *boxrect=GetWindowLong_(hwnd, #GWL_USERDATA)
  With drawrect
    \left=*boxrect\LocRect\left+dx
    \right=*boxrect\LocRect\right+dx
    \top=*boxrect\LocRect\top+dy
    \bottom=*boxrect\LocRect\bottom+dy
    ; Added by r_hyde
    If \left < 0
      \left = 0
      \right = *boxrect\LocRect\right - *boxrect\LocRect\left
    ElseIf \right >= ImageWidth(*boxrect\pbimage)
      \right = ImageWidth(*boxrect\pbimage) - 1
      \left = \right - (*boxrect\LocRect\right - *boxrect\LocRect\left)
    EndIf
    If \top < 0
      \top = 0
      \bottom = *boxrect\LocRect\bottom - *boxrect\LocRect\top
    ElseIf \bottom >= ImageHeight(*boxrect\pbimage)
      \bottom = ImageHeight(*boxrect\pbimage) - 1
      \top = \bottom - (*boxrect\LocRect\bottom - *boxrect\LocRect\top)
    EndIf
  EndWith
  DrawSelectRect(drawrect.RECT, *boxrect\pbID, *boxrect\pbimage)
  SendMessage_(hwnd, #Icon_Rect_Change, drawrect.RECT, 0)
EndProcedure

Procedure NudgeNode(hwnd, node, dx, dy) ; AKJ
; Move a selection rectangle node (corner) by a given offset
; This code is modified from the #WM_MOUSEMOVE case of IconProc()
  Protected dxy, sizeold, sizenew, *boxrect.iconbox, w, h
  If node<1 Or node>4: ProcedureReturn: EndIf ; Redundant? !!!
  If Abs(dx)>Abs(dy) ; If greater change is in X movement
    If node=2 Or node=4: dxy = dx: Else: dxy = -dx: EndIf
  Else
    If node=3 Or node=4: dxy = dy: Else: dxy = -dy: EndIf
  EndIf
  *boxrect=GetWindowLong_(hwnd, #GWL_USERDATA)
  With drawrect
    \left=*boxrect\LocRect\left
    \right=*boxrect\LocRect\right
    \top=*boxrect\LocRect\top
    \bottom=*boxrect\LocRect\bottom
    sizeold = \right-\left
    sizenew = sizeold+dxy
    If sizenew<32: sizenew = 32: EndIf
    dxy = sizenew-sizeold
    w = ImageWidth(*boxrect\pbimage)
    h = ImageHeight(*boxrect\pbimage)
    Select node
      Case 1: \left - dxy: \top - dxy
              While \left<0 Or \top<0: \left+1: \top+1: Wend
      Case 2: \right + dxy: \top - dxy
              While \right>w Or \top<0: \right-1: \top+1: Wend
      Case 3: \left - dxy: \bottom + dxy
              While \left<0 Or \bottom>h: \left+1: \bottom-1: Wend
      Case 4: \right + dxy: \bottom + dxy
              While \right>w Or \bottom>h: \right-1: \bottom-1: Wend
    EndSelect
  EndWith
  DrawRect(drawrect.RECT, *boxrect\pbID, *boxrect\pbimage)
EndProcedure

Procedure.l IconProc(hwnd, msg, wParam, lParam)
  Protected hCurHand, mte.myTRACKMOUSEEVENT, *boxrect.iconbox ; AKJ
  Protected xPos, yPos, therect.RECT, rect.RECT, point.POINT ; AKJ
  Protected MouseOffsetX.w, MouseOffsetY.w, Resultimage ; AKJ

  Select msg

    Case #WM_PAINT

    Case #WM_KEYDOWN ; AKJ See if an arrow key is pressed
      If node
        Select wParam
          Case #VK_LEFT : NudgeNode(hwnd, node, -1, 0)
          Case #VK_RIGHT : NudgeNode(hwnd, node, 1, 0)
          Case #VK_UP : NudgeNode(hwnd, node, 0, -1)
          Case #VK_DOWN : NudgeNode(hwnd, node, 0, 1)
        EndSelect ; wParam
        DrawSelectRect(drawrect.RECT,*box\pbID,*box\pbimage)
        SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
      Else
        Select wParam
          Case #VK_LEFT : NudgeRect(hwnd, -1, 0)
          Case #VK_RIGHT : NudgeRect(hwnd, 1, 0)
          Case #VK_UP : NudgeRect(hwnd, 0, -1)
          Case #VK_DOWN : NudgeRect(hwnd, 0, 1)
        EndSelect ; wParam
      EndIf ; node

    Case #WM_LBUTTONDOWN
      *boxrect=GetWindowLong_(hwnd,#GWL_USERDATA)
      xPos = LOWORD(lParam)
      yPos = HIWORD(lParam)
      MouseBtnDownX=LOWORD(lParam)
      MouseBtnDownY=HIWORD(lParam)
      With therect
        \left=*boxrect\LocRect\left
        \right=*boxrect\LocRect\right
        \top=*boxrect\LocRect\top
        \bottom=*boxrect\LocRect\bottom
      EndWith
      If PtInRect_(therect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_HAND)
        SetCursor_(hCurHand)
        SetCapture_(hwnd)
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
        mousedown=1: node = 0 ; AKJ
      ElseIf PtInRect_(*boxrect\TLrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        mousedowntopleft.l=1: node = 1 ; AKJ
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
      ElseIf PtInRect_(*boxrect\TRrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENESW   )
        SetCursor_(hCurHand)
        mousedowntopright=1: node = 2 ; AKJ
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
      ElseIf PtInRect_(*boxrect\BLrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENESW   )
        SetCursor_(hCurHand)
        mousedownbotleft=1: node = 3 ; AKJ
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
      ElseIf PtInRect_(*boxrect\BRrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        mousedownbotright=1: node = 4 ; AKJ
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
      EndIf
      ProcedureReturn 0

    Case #WM_LBUTTONUP
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      ClipCursor_(#Null)
      If mousedowntopleft=1 Or mousedowntopright=1 Or mousedownbotleft=1 Or mousedownbotright=1
        DrawSelectRect(drawrect.RECT,*box\pbID,*box\pbimage)
        SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
      EndIf
      mousedown=0
      mousedowntopleft=0
      mousedowntopright=0
      mousedownbotleft=0
      mousedownbotright=0
      ReleaseCapture_()

    Case #WM_RBUTTONDOWN

    Case #WM_RBUTTONUP

    Case #WM_MOUSEMOVE
      GetCursorPos_(point)
      ScreenToClient_(hwnd,point)
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      mte\cbSize = SizeOf(myTRACKMOUSEEVENT)
      mte\dwFlags = #TME_LEAVE
      mte\hwndTrack = hwnd
      TrackMouseEvent_(mte)
      xPos = LOWORD(lParam)
      yPos = HIWORD(lParam)
      With therect
        \left=*boxrect\LocRect\left
        \right=*boxrect\LocRect\right
        \top=*boxrect\LocRect\top
        \bottom=*boxrect\LocRect\bottom
      EndWith
      If PtInRect_(therect,xPos,yPos) And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_HAND)
        SetCursor_(hCurHand)

        If mousedown=1
          MouseOffsetX = lParam&$FFFF - MouseBtnDownX
          MouseOffsetY = (lParam>>16) - MouseBtnDownY
          NudgeRect(hwnd, MouseOffsetX, MouseOffsetY) ; AKJ
          ; AKJ Many lines moved to NudgeRect()
          MouseBtnDownX + MouseOffsetX
          MouseBtnDownY + MouseOffsetY
        EndIf ; mousedown=1

      ElseIf PtInRect_(*boxrect\TLrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
      ElseIf PtInRect_(*boxrect\TRrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_SIZENESW   )
        SetCursor_(hCurHand)
      ElseIf PtInRect_(*boxrect\BLrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_SIZENESW   )
        SetCursor_(hCurHand)
      ElseIf PtInRect_(*boxrect\BRrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
      EndIf

      If mousedowntopleft=1   ; Keep in mind here that we want a SQUARE, so the greatest change in movement is forced to be accepted for both X and Y
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF - MouseBtnDownX
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY
        NudgeNode(hwnd, 1, MouseOffsetX, MouseOffsetY) ; AKJ
        ; AKJ Many lines moved to NudgeNode()
      ElseIf mousedowntopright=1
        hCurHand = LoadCursor_(0,#IDC_SIZENESW)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF - MouseBtnDownX
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY
        NudgeNode(hwnd, 2, MouseOffsetX, MouseOffsetY) ; AKJ
        ; AKJ Many lines moved to NudgeNode()
      ElseIf mousedownbotleft=1
        hCurHand = LoadCursor_(0,#IDC_SIZENESW)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF - MouseBtnDownX
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY
        NudgeNode(hwnd, 3, MouseOffsetX, MouseOffsetY) ; AKJ
        ; AKJ Many lines moved to NudgeNode()
      ElseIf mousedownbotright=1
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF - MouseBtnDownX
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY
        NudgeNode(hwnd, 4, MouseOffsetX, MouseOffsetY) ; AKJ
        ; AKJ Many lines moved to NudgeNode()
      EndIf
      ProcedureReturn 0

    Case #WM_MOUSEHOVER

    Case #WM_MOUSELEAVE

    Case #Icon_Rect_Change
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      Resultimage = GrabImage(*boxrect\pbimage, #PB_Any, *boxrect\LocRect\left, *boxrect\LocRect\top, *boxrect\LocRect\right-*boxrect\LocRect\left, *boxrect\LocRect\bottom-*boxrect\LocRect\top)
      StartDrawing(ImageOutput(*boxrect\PBimage32))
      DrawImage(ImageID(Resultimage),0,0,32,32)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage48))
      DrawImage(ImageID(Resultimage),0,0,48,48)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage64))
      DrawImage(ImageID(Resultimage),0,0,64,64)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage128))
      DrawImage(ImageID(Resultimage),0,0,128,128)
      StopDrawing()
      SetGadgetState(*boxrect\image32,ImageID(*boxrect\PBimage32))
      SetGadgetState(*boxrect\image48,ImageID(*boxrect\PBimage48))
      SetGadgetState(*boxrect\image64,ImageID(*boxrect\PBimage64))
      SetGadgetState(*boxrect\image128,ImageID(*boxrect\PBimage128))
      FreeImage(Resultimage)
  EndSelect
  ProcedureReturn CallWindowProc_(GetProp_(hwnd,"oldproc"),hwnd,msg,wParam,lParam)
EndProcedure

Procedure.l IconGadget(id.l,x,y,width,height) ; AKJ Return gadget's handle
  Protected image, imagegad, container, hwnd ; AKJ
  Protected PBimage32, PBimage48, PBimage64, PBimage128 ; AKJ
  Protected image32, image48, image64, image128 ; AKJ
  image=CreateImage(#PB_Any,300,300)
  StartDrawing(ImageOutput(image))
  Box(0,0,300,300,#White)
  Circle(150,150,60,#Red)
  StopDrawing()
  container=ContainerGadget(#PB_Any,x,y,width+154,height+20,#PB_Container_Raised)
  imagegad=ImageGadget(id,5,5,width,height,ImageID(image),#PB_Image_Border)
  PBimage32=CreateImage(#PB_Any,32,32)
  PBimage48=CreateImage(#PB_Any,48,48)
  PBimage64=CreateImage(#PB_Any,64,64)
  PBimage128=CreateImage(#PB_Any,128,128)
  image32.l=ImageGadget(#PB_Any,width+64,10,32,32,ImageID(PBimage32),#PB_Image_Border)
  image48.l=ImageGadget(#PB_Any,width+56,50,48,48,ImageID(PBimage48),#PB_Image_Border)
  image64.l=ImageGadget(#PB_Any,width+46,107,64,64,ImageID(PBimage64),#PB_Image_Border)
  image128.l=ImageGadget(#PB_Any,width+14,180,128,128,ImageID(PBimage128),#PB_Image_Border)
  CloseGadgetList()
  drawrect\left=width/2-50 ; AKJ Was rect\ - Bug?
  drawrect\right=width/2+50 ; AKJ Was rect\ - Bug?
  drawrect\top=height/2-50 ; AKJ Was rect\ - Bug?
  drawrect\bottom=height/2+50 ; AKJ Was rect\ - Bug?
  If id=#PB_Any
    *box\pbID=imagegad
    ;AKJ hwndreturn=imagegad
    hwnd=GadgetID(imagegad)
  Else
    *box\pbID=id
    ;AKJ hwndreturn=imagegad
    hwnd=imagegad
  EndIf
  *box\width=width
  *box\height=height
  *box\pbimage=image
  *box\image32=image32
  *box\image48=image48
  *box\image64=image64
  *box\image128=image128
  *box\PBimage32=PBimage32
  *box\PBimage48=PBimage48
  *box\PBimage64=PBimage64
  *box\PBimage128=PBimage128
  SetWindowLong_(hwnd,#GWL_USERDATA,*box)
  SetProp_(hwnd,"oldproc",SetWindowLong_(hwnd,#GWL_WNDPROC,@IconProc()))
  DrawSelectRect(drawrect.RECT,*box\pbID,image) ; AKJ Was rect.RECT - Bug?
  SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
  ProcedureReturn hwnd ; AKJ
EndProcedure

Procedure SetIconGadgetImage(icongadget,PBimageNumber)
  Protected *boxrect.iconbox, newimage, tempimage, rect.RECT ; AKJ
  *boxrect=GetWindowLong_(GadgetID(icongadget),#GWL_USERDATA)
  newimage=ScaleImage(ImageID(PBimageNumber),*box\width,*box\height,#White)
  ResizeImage(newimage,*box\width,*box\height)
  tempimage=CopyImage(newimage,#PB_Any)
  If IsImage(*boxrect\pbimage)
    FreeImage(*boxrect\pbimage)
  EndIf
  If IsImage(*boxrect\tempimage)
    FreeImage(*boxrect\tempimage)
  EndIf
  *boxrect\pbimage=newimage
  *boxrect\tempimage=tempimage
  SetGadgetState(icongadget,ImageID(newimage))
  SetWindowLong_(GadgetID(icongadget),#GWL_USERDATA,*boxrect)
  rect\left=GadgetWidth(*boxrect\pbID)/2-50
  rect\right=GadgetWidth(*boxrect\pbID)/2 +50
  rect\top=GadgetHeight(*boxrect\pbID)/2-50
  rect\bottom=GadgetHeight(*boxrect\pbID)/2+50
  DrawSelectRect(rect.RECT,*boxrect\pbID,newimage)
  FreeImage(PBimageNumber)
  SendMessage_(GadgetID(*boxrect\pbID),#Icon_Rect_Change, drawrect.RECT,0)
EndProcedure

;-Main program
Define hwnd, imagefile$, image, Quit=0 ; AKJ
UseJPEGImageDecoder()
UsePNGImageDecoder()
If OpenWindow(0, 259, 217, 605, 388, "IconMaker Gadget",  #PB_Window_SystemMenu |  #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  If CreateGadgetList(WindowID(0))
    hwnd = IconGadget(40,40,40,300,300) ; AKJ
    ButtonGadget(1,40,10,90,25,"Open Image") ; AKJ Cater for large fonts
  EndIf
EndIf

;-Event Loop
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventGadget()
      Case 1 ; Button gadget
        imagefile$=OpenFileRequester("Open An Image","","Images|*.bmp;*.jpg;*.png",0)
        If imagefile$
          image=LoadImage(#PB_Any,imagefile$)
          SetIconGadgetImage(10,image)
        EndIf
    EndSelect
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
    Case #WM_KEYDOWN ; AKJ See if a key is pressed
      SendMessage_(hwnd, #WM_KEYDOWN, EventwParam(), EventlParam()) ; Relay message
    Case #PB_Event_CloseWindow
      Quit=1
  EndSelect
Until Quit=1

End

Posted: Sun Feb 17, 2008 11:38 am
by Demivec
@akj: I made eight corrections to the code modifications you posted. Six were related to uncorrections you made for Bugs that didn't exist, one added a missing variable declaration and the other was a Bug you created by what was probably a typo. Here's is the corrected code with the changes (and comments) indicated by "Demivec -". I don't need my name in the source BTW, this was just to document the changes for this posting.

These were made to correct the undesirable effect of not being able to load an image into the gadget any more. Your improvements now shine a little bit brighter on localmotion34's gadget.:wink:

Additional corrections and updates listed at bottom.

Code: Select all

; IconMaker Gadget  16-Feb-08  ;updated 17-Feb-08 by Demivec
; By localmotion34
; www.purebasic.fr/english/viewtopic.php?t=31133

EnableExplicit ; AKJ

#WM_MOUSEHOVER = $2A1
#WM_MOUSELEAVE = $2A3
#TME_HOVER = 1
#TME_LEAVE = 2

#Icon_Rect_Change=$456

Structure iconbox
  width.l
  height.l
  pbID.l ;PB gadget number
  pbimage.l ; this is the REAL image that we load or create
  TLrect.RECT ;location for the top left grab box
  TRrect.RECT  ;""
  BLrect.RECT ;""
  BRrect.RECT ;""
  LocRect.RECT  ;this is the actual rectangle of the selection box
  tempimage.l ;we dont want to mess up the real image, so we ALWAYS draw on this one
  image32.l ;32x32 image gadget
  image48.l ;""
  image64.l ;""
  image128.l ;""
  PBimage32.l ;this is the image associated with the 32x32 - we just redraw over this to save memory and creating constant new images
  PBimage48.l ;""
  PBimage64.l ;""
  PBimage128.l ;""
EndStructure

Structure myTRACKMOUSEEVENT ; AKJ
  cbSize.l
  dwFlags.l
  hwndTrack.l
  dwHoverTime.l
EndStructure

Global*box.iconbox=AllocateMemory(SizeOf(iconbox))
Global mousedown.l,MouseBtnDownX,MouseBtnDownY,mousedowntopleft.l, mousedowntopright.l, mousedownbotleft.l,mousedownbotright.l, drawrect.RECT
Global node.l=0 ; AKJ Selected node (corner)  0=none  1=topleft  2=topright  3=botleft  4=botright

Procedure.w LOWORD(Value.l) ;windef.h macro
  ProcedureReturn (Value & $FFFF)
EndProcedure

Procedure.w HIWORD(Value.l) ;windef.h macro
  ProcedureReturn ((Value >> 16) & $FFFF)
EndProcedure

Procedure.l ScaleImage(hBitmap,width.l,height.l,COLOR.l)
  Protected OriW, OriH, w, h, oriAR, newAR ; AKJ
  Protected fw.d, fh.d ; AKJ
  Protected tempimage, fixx, fixy, newPhoto, newdc, bz.BITMAP ; AKJ  Demivec -removed hdc as unused
  GetObject_(hBitmap,SizeOf(BITMAP),bz)
  OriW=bz\bmWidth
  OriH=bz\bmHeight
  tempimage=CreateImage(#PB_Any,bz\bmWidth,bz\bmHeight)
  StartDrawing(ImageOutput(tempimage)) ;Demivec-removed hdc as unneeded
  DrawImage(hBitmap,0,0)
  StopDrawing()
  
  If (OriH > OriW And height < width) Or (OriH < OriW And height > width)
    Swap width, height
  EndIf
  
  ; Calc Factor
  fw = width/OriW
  fh = height/OriH
  
  ; Calc AspectRatio
  oriAR = Round((OriW / OriH) * 10,0)
  newAR = Round((width / height) * 10,0)
  
  ; AspectRatio already correct?
  If oriAR = newAR
    w = width
    h = height
  ElseIf OriW * fh <= width
    w = OriW * fh
    h = OriH * fh
  ElseIf OriH * fw <= height
    w = OriW * fw
    h = OriH * fw
  EndIf
  
  fixx=(width/2)-(w/2)
  fixy=(height/2)-(h/2)
  ResizeImage(tempimage,w,h,#PB_Image_Smooth)
  newPhoto=CreateImage(#PB_Any,width,height)
  StartDrawing(ImageOutput(newPhoto)) ;AKJ was hdc - Bug?  Demivec-removed hdc as unneeded
  ;SelectObject_(0,hBitmap) ;Demivec-seems to not be needed
  Box(0,0,width,height,COLOR)
  DrawImage(ImageID(tempimage), fixx,fixy)
  StopDrawing()
  FreeImage(tempimage)
  ProcedureReturn newPhoto
EndProcedure

Procedure DrawSelectRect(*rect.RECT,Gadget,numberimage)
  ; Draw selection rectangle and nodes
  Protected *box.iconbox, width, height, tempimage, colour ; AKJ
  *box=GetWindowLong_(GadgetID(Gadget),#GWL_USERDATA)
  If *box\tempimage
    FreeImage(*box\tempimage);get rid of it and start over
  EndIf
  tempimage=CreateImage(#PB_Any,*box\width, *box\height)
  StartDrawing(ImageOutput(tempimage))
  DrawImage(ImageID(numberimage),0,0) ;draw the REAL image associated with the gadget
  DrawingMode(#PB_2DDrawing_Outlined)
  width=*rect\right-*rect\left
  height=*rect\bottom-*rect\top
  Box(*rect\left,*rect\top,width,height, #Blue);actual selection box
  DrawingMode(#PB_2DDrawing_Default)
  LineXY(*rect\left+width/2,*rect\top,*rect\left+width/2,*rect\bottom,#Blue)
  LineXY(*rect\left,*rect\top+height/2,*rect\right,*rect\top+height/2,#Blue)
  Box(*rect\left-6,*rect\top-6,6,6,#Blue); Top Left
  Box(*rect\right,*rect\top-6,6,6,#Blue)  ;Top Right
  Box(*rect\left-6,*rect\bottom,6,6,#Blue) ;Bottom Left
  Box(*rect\right,*rect\bottom,6,6,#Blue) ;Bottom Left
  ; AKJ Highlight the selected corner node of the box
  colour = #Yellow
  Select node
    Case 1: Box(*rect\left-5,*rect\top-5,4,4,colour)
    Case 2: Box(*rect\right+1,*rect\top-5,4,4,colour)
    Case 3: Box(*rect\left-5,*rect\bottom+1,4,4,colour)
    Case 4: Box(*rect\right+1,*rect\bottom+1,4,4,colour)
  EndSelect
  StopDrawing()
  SetGadgetState(Gadget,ImageID(tempimage))
  
  With *box
    *box\TLrect\left=*rect\left-6
    *box\TLrect\top=*rect\top-6
    *box\TLrect\right=*rect\left
    *box\TLrect\bottom=*rect\top
    
    *box\TRrect\left=*rect\right
    *box\TRrect\top=*rect\top-6
    *box\TRrect\right=*rect\right+6
    *box\TRrect\bottom =*rect\top
    
    *box\BLrect\left=*rect\left-6
    *box\BLrect\top=*rect\bottom
    *box\BLrect\right=*rect\left
    *box\BLrect\bottom=*rect\bottom+6
    
    *box\BRrect\left=*rect\right
    *box\BRrect\top=*rect\bottom
    *box\BRrect\right=*rect\right+6
    *box\BRrect\bottom=*rect\bottom+6
    
    *box\LocRect\left=*rect\left
    *box\LocRect\right=*rect\right
    *box\LocRect\top=*rect\top
    *box\LocRect\bottom=*rect\bottom
    
    *box\tempimage=tempimage
  EndWith
  SetWindowLong_(GadgetID(Gadget),#GWL_USERDATA,*box)
EndProcedure

Procedure DrawRect(*rect.RECT,Gadget,numberimage)
  ; Draw rectangle (without nodes)
  Protected *boxrect.iconbox, tempimage, width, height ; AKJ
  *boxrect=GetWindowLong_(GadgetID(Gadget),#GWL_USERDATA)
  If *boxrect\tempimage
    FreeImage(*boxrect\tempimage)
  EndIf
  tempimage=CreateImage(#PB_Any, *boxrect\width, *boxrect\height)
  StartDrawing(ImageOutput(tempimage))
  DrawImage(ImageID(numberimage),0,0)
  DrawingMode(#PB_2DDrawing_Outlined)
  width=*rect\right-*rect\left
  height=*rect\bottom-*rect\top
  Box(*rect\left,*rect\top,width,height, #Blue)
  StopDrawing()
  SetGadgetState(Gadget,ImageID(tempimage))
EndProcedure

Procedure NudgeRect(hwnd, dx, dy) ; AKJ
  ; Move the selection rectangle by a given offset
  ; This code is replicated from the #WM_MOUSEMOVE case of IconProc()
  Protected *boxrect.iconbox
  *boxrect=GetWindowLong_(hwnd, #GWL_USERDATA)
  With drawrect
    \left=*boxrect\LocRect\left+dx
    \right=*boxrect\LocRect\right+dx
    \top=*boxrect\LocRect\top+dy
    \bottom=*boxrect\LocRect\bottom+dy
    ; Added by r_hyde
    If \left < 0
      \left = 0
      \right = *boxrect\LocRect\right - *boxrect\LocRect\left
    ElseIf \right >= ImageWidth(*boxrect\pbimage)
      \right = ImageWidth(*boxrect\pbimage) - 1
      \left = \right - (*boxrect\LocRect\right - *boxrect\LocRect\left)
    EndIf
    If \top < 0
      \top = 0
      \bottom = *boxrect\LocRect\bottom - *boxrect\LocRect\top
    ElseIf \bottom >= ImageHeight(*boxrect\pbimage)
      \bottom = ImageHeight(*boxrect\pbimage) - 1
      \top = \bottom - (*boxrect\LocRect\bottom - *boxrect\LocRect\top)
    EndIf
  EndWith
  DrawSelectRect(drawrect.RECT, *boxrect\pbID, *boxrect\pbimage)
  SendMessage_(hwnd, #Icon_Rect_Change, drawrect.RECT, 0)
EndProcedure

Procedure NudgeNode(hwnd, node, dx, dy) ; AKJ
  ; Move a selection rectangle node (corner) by a given offset
  ; This code is modified from the #WM_MOUSEMOVE case of IconProc()
  Protected dxy, sizeold, sizenew, *boxrect.iconbox, w, h
  If node<1 Or node>4: ProcedureReturn: EndIf ; Redundant? !!!
  If Abs(dx)>Abs(dy) ; If greater change is in X movement
    If node=2 Or node=4: dxy = dx: Else: dxy = -dx: EndIf
  Else
    If node=3 Or node=4: dxy = dy: Else: dxy = -dy: EndIf
  EndIf
  *boxrect=GetWindowLong_(hwnd, #GWL_USERDATA)
  With drawrect
    \left=*boxrect\LocRect\left
    \right=*boxrect\LocRect\right
    \top=*boxrect\LocRect\top
    \bottom=*boxrect\LocRect\bottom
    sizeold = \right-\left
    sizenew = sizeold+dxy
    If sizenew<32: sizenew = 32: EndIf
    dxy = sizenew-sizeold
    w = ImageWidth(*boxrect\pbimage)
    h = ImageHeight(*boxrect\pbimage)
    Select node
      Case 1: \left - dxy: \top - dxy
        While \left<0 Or \top<0: \left+1: \top+1: Wend
      Case 2: \right + dxy: \top - dxy
        While \right>w Or \top<0: \right-1: \top+1: Wend
      Case 3: \left - dxy: \bottom + dxy
        While \left<0 Or \bottom>h: \left+1: \bottom-1: Wend
      Case 4: \right + dxy: \bottom + dxy
        While \right>w Or \bottom>h: \right-1: \bottom-1: Wend
    EndSelect
  EndWith
  DrawRect(drawrect.RECT, *boxrect\pbID, *boxrect\pbimage)
EndProcedure

Procedure.l IconProc(hwnd, msg, wParam, lParam)
  Protected hCurHand, mte.myTRACKMOUSEEVENT, *boxrect.iconbox ; AKJ
  Protected xPos, yPos, therect.RECT, rect.RECT, point.POINT ; AKJ
  Protected MouseOffsetX.w, MouseOffsetY.w, Resultimage ; AKJ
  
  Select msg
    
    Case #WM_PAINT
      
    Case #WM_KEYDOWN ; AKJ See if an arrow key is pressed
      If node
        Select wParam
          Case #VK_LEFT : NudgeNode(hwnd, node, -1, 0)
          Case #VK_RIGHT : NudgeNode(hwnd, node, 1, 0)
          Case #VK_UP : NudgeNode(hwnd, node, 0, -1)
          Case #VK_DOWN : NudgeNode(hwnd, node, 0, 1)
        EndSelect ; wParam
        DrawSelectRect(drawrect.RECT,*box\pbID,*box\pbimage)
        SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
      Else
        Select wParam
          Case #VK_LEFT : NudgeRect(hwnd, -1, 0)
          Case #VK_RIGHT : NudgeRect(hwnd, 1, 0)
          Case #VK_UP : NudgeRect(hwnd, 0, -1)
          Case #VK_DOWN : NudgeRect(hwnd, 0, 1)
        EndSelect ; wParam
      EndIf ; node
      
    Case #WM_LBUTTONDOWN
      *boxrect=GetWindowLong_(hwnd,#GWL_USERDATA)
      xPos = LOWORD(lParam)
      yPos = HIWORD(lParam)
      MouseBtnDownX=LOWORD(lParam)
      MouseBtnDownY=HIWORD(lParam)
      With therect
        \left=*boxrect\LocRect\left
        \right=*boxrect\LocRect\right
        \top=*boxrect\LocRect\top
        \bottom=*boxrect\LocRect\bottom
      EndWith
      If PtInRect_(therect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_HAND)
        SetCursor_(hCurHand)
        SetCapture_(hwnd)
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
        mousedown=1: node = 0 ; AKJ
      ElseIf PtInRect_(*boxrect\TLrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        mousedowntopleft.l=1: node = 1 ; AKJ
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
      ElseIf PtInRect_(*boxrect\TRrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENESW   )
        SetCursor_(hCurHand)
        mousedowntopright=1: node = 2 ; AKJ
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
      ElseIf PtInRect_(*boxrect\BLrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENESW   )
        SetCursor_(hCurHand)
        mousedownbotleft=1: node = 3 ; AKJ
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
      ElseIf PtInRect_(*boxrect\BRrect,xPos,yPos)
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        mousedownbotright=1: node = 4 ; AKJ
        GetWindowRect_(hwnd,rect)
        ClipCursor_(rect)
      EndIf
      ProcedureReturn 0
      
    Case #WM_LBUTTONUP
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      ClipCursor_(#Null)
      If mousedowntopleft=1 Or mousedowntopright=1 Or mousedownbotleft=1 Or mousedownbotright=1
        DrawSelectRect(drawrect.RECT,*box\pbID,*box\pbimage)
        SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
      EndIf
      mousedown=0
      mousedowntopleft=0
      mousedowntopright=0
      mousedownbotleft=0
      mousedownbotright=0
      ReleaseCapture_()
      
    Case #WM_RBUTTONDOWN
      
    Case #WM_RBUTTONUP
      
    Case #WM_MOUSEMOVE
      GetCursorPos_(point)
      ScreenToClient_(hwnd,point)
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      mte\cbSize = SizeOf(myTRACKMOUSEEVENT)
      mte\dwFlags = #TME_LEAVE
      mte\hwndTrack = hwnd
      TrackMouseEvent_(mte)
      xPos = LOWORD(lParam)
      yPos = HIWORD(lParam)
      With therect
        \left=*boxrect\LocRect\left
        \right=*boxrect\LocRect\right
        \top=*boxrect\LocRect\top
        \bottom=*boxrect\LocRect\bottom
      EndWith
      If PtInRect_(therect,xPos,yPos) And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_HAND)
        SetCursor_(hCurHand)
        
        If mousedown=1
          MouseOffsetX = lParam&$FFFF - MouseBtnDownX
          MouseOffsetY = (lParam>>16) - MouseBtnDownY
          NudgeRect(hwnd, MouseOffsetX, MouseOffsetY) ; AKJ
          ; AKJ Many lines moved to NudgeRect()
          MouseBtnDownX + MouseOffsetX
          MouseBtnDownY + MouseOffsetY
        EndIf ; mousedown=1
        
      ElseIf PtInRect_(*boxrect\TLrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
      ElseIf PtInRect_(*boxrect\TRrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_SIZENESW   )
        SetCursor_(hCurHand)
      ElseIf PtInRect_(*boxrect\BLrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_SIZENESW   )
        SetCursor_(hCurHand)
      ElseIf PtInRect_(*boxrect\BRrect,xPos,yPos)And mousedowntopleft=0 And mousedowntopright=0 And mousedownbotleft=0 And mousedownbotright=0
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
      EndIf
      
      If mousedowntopleft=1   ; Keep in mind here that we want a SQUARE, so the greatest change in movement is forced to be accepted for both X and Y
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF - MouseBtnDownX
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY
        NudgeNode(hwnd, 1, MouseOffsetX, MouseOffsetY) ; AKJ
        ; AKJ Many lines moved to NudgeNode()
      ElseIf mousedowntopright=1
        hCurHand = LoadCursor_(0,#IDC_SIZENESW)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF - MouseBtnDownX
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY
        NudgeNode(hwnd, 2, MouseOffsetX, MouseOffsetY) ; AKJ
        ; AKJ Many lines moved to NudgeNode()
      ElseIf mousedownbotleft=1
        hCurHand = LoadCursor_(0,#IDC_SIZENESW)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF - MouseBtnDownX
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY
        NudgeNode(hwnd, 3, MouseOffsetX, MouseOffsetY) ; AKJ
        ; AKJ Many lines moved to NudgeNode()
      ElseIf mousedownbotright=1
        hCurHand = LoadCursor_(0,#IDC_SIZENWSE)
        SetCursor_(hCurHand)
        MouseOffsetX.w = lParam&$FFFF - MouseBtnDownX
        MouseOffsetY.w = (lParam>>16) - MouseBtnDownY
        NudgeNode(hwnd, 4, MouseOffsetX, MouseOffsetY) ; AKJ
        ; AKJ Many lines moved to NudgeNode()
      EndIf
      ProcedureReturn 0
      
    Case #WM_MOUSEHOVER
      
    Case #WM_MOUSELEAVE
      
    Case #Icon_Rect_Change
      *boxrect.iconbox=GetWindowLong_(hwnd,#GWL_USERDATA)
      Resultimage = GrabImage(*boxrect\pbimage, #PB_Any, *boxrect\LocRect\left, *boxrect\LocRect\top, *boxrect\LocRect\right-*boxrect\LocRect\left, *boxrect\LocRect\bottom-*boxrect\LocRect\top)
      StartDrawing(ImageOutput(*boxrect\PBimage32))
      DrawImage(ImageID(Resultimage),0,0,32,32)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage48))
      DrawImage(ImageID(Resultimage),0,0,48,48)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage64))
      DrawImage(ImageID(Resultimage),0,0,64,64)
      StopDrawing()
      StartDrawing(ImageOutput(*boxrect\PBimage128))
      DrawImage(ImageID(Resultimage),0,0,128,128)
      StopDrawing()
      SetGadgetState(*boxrect\image32,ImageID(*boxrect\PBimage32))
      SetGadgetState(*boxrect\image48,ImageID(*boxrect\PBimage48))
      SetGadgetState(*boxrect\image64,ImageID(*boxrect\PBimage64))
      SetGadgetState(*boxrect\image128,ImageID(*boxrect\PBimage128))
      FreeImage(Resultimage)
  EndSelect
  ProcedureReturn CallWindowProc_(GetProp_(hwnd,"oldproc"),hwnd,msg,wParam,lParam)
EndProcedure

Procedure.l IconGadget(id.l,x,y,width,height) ; AKJ Return gadget's handle
  Protected image, imagegad, container, hwnd ; AKJ
  Protected PBimage32, PBimage48, PBimage64, PBimage128 ; AKJ
  Protected image32, image48, image64, image128 ; AKJ
   
  image=CreateImage(#PB_Any,300,300)
  StartDrawing(ImageOutput(image))
  Box(0,0,300,300,#White)
  Circle(150,150,60,#Red)
  StopDrawing()
  container=ContainerGadget(#PB_Any,x,y,width+154,height+20,#PB_Container_Raised)
  imagegad=ImageGadget(id,5,5,width,height,ImageID(image),#PB_Image_Border)
  PBimage32=CreateImage(#PB_Any,32,32)
  PBimage48=CreateImage(#PB_Any,48,48)
  PBimage64=CreateImage(#PB_Any,64,64)
  PBimage128=CreateImage(#PB_Any,128,128)
  image32.l=ImageGadget(#PB_Any,width+64,10,32,32,ImageID(PBimage32),#PB_Image_Border)
  image48.l=ImageGadget(#PB_Any,width+56,50,48,48,ImageID(PBimage48),#PB_Image_Border)
  image64.l=ImageGadget(#PB_Any,width+46,107,64,64,ImageID(PBimage64),#PB_Image_Border)
  image128.l=ImageGadget(#PB_Any,width+14,180,128,128,ImageID(PBimage128),#PB_Image_Border)
  CloseGadgetList()
  drawrect\left=width/2-50 ; AKJ Was rect\ - Bug?  Demivec -Yes
  drawrect\right=width/2+50 ; AKJ Was rect\ - Bug? Demivec -Yes
  drawrect\top=height/2-50 ; AKJ Was rect\ - Bug? Demivec -Yes
  drawrect\bottom=height/2+50 ; AKJ Was rect\ - Bug? Demivec -Yes
  If id=#PB_Any
    *box\pbID=imagegad
    ;AKJ hwndreturn=imagegad
    hwnd=GadgetID(imagegad)
  Else
    *box\pbID=id
    ;AKJ hwndreturn=imagegad
    hwnd=imagegad
  EndIf
  *box\width=width
  *box\height=height
  *box\pbimage=image
  *box\image32=image32
  *box\image48=image48
  *box\image64=image64
  *box\image128=image128
  *box\PBimage32=PBimage32
  *box\PBimage48=PBimage48
  *box\PBimage64=PBimage64
  *box\PBimage128=PBimage128
  SetWindowLong_(hwnd,#GWL_USERDATA,*box)
  SetProp_(hwnd,"oldproc",SetWindowLong_(hwnd,#GWL_WNDPROC,@IconProc()))
  DrawSelectRect(drawrect.RECT,*box\pbID,image) ; AKJ Was rect.RECT - Bug? Demivec -Yes
  SendMessage_(hwnd,#Icon_Rect_Change, drawrect.RECT,0)
  ProcedureReturn hwnd ; AKJ
EndProcedure

Procedure SetIconGadgetImage(icongadget,PBimageNumber)
  Protected *boxrect.iconbox, newimage, tempimage ; AKJ  Demivec -removed rect.RECT as unused
  *boxrect=GetWindowLong_(GadgetID(icongadget),#GWL_USERDATA)
  newimage=ScaleImage(ImageID(PBimageNumber),*box\width,*box\height,#White)
  ResizeImage(newimage,*box\width,*box\height)
  tempimage=CopyImage(newimage,#PB_Any)
  If IsImage(*boxrect\pbimage)
    FreeImage(*boxrect\pbimage)
  EndIf
  If IsImage(*boxrect\tempimage)
    FreeImage(*boxrect\tempimage)
  EndIf
  *boxrect\pbimage=newimage
  *boxrect\tempimage=tempimage
  SetGadgetState(icongadget,ImageID(newimage))
  SetWindowLong_(GadgetID(icongadget),#GWL_USERDATA,*boxrect)
  drawrect\left=GadgetWidth(*boxrect\pbID)/2-50 ;Demivec - a Bug, replaced rect with drawrect
  drawrect\right=GadgetWidth(*boxrect\pbID)/2 +50 ;Demivec - a Bug, replaced rect with drawrect
  drawrect\top=GadgetHeight(*boxrect\pbID)/2-50 ;Demivec - a Bug, replaced rect with drawrect
  drawrect\bottom=GadgetHeight(*boxrect\pbID)/2+50 ;Demivec - a Bug, replaced rect with drawrect
  DrawSelectRect(drawrect.RECT,*boxrect\pbID,newimage) ;Demivec - a Bug, replaced rect with drawrect
  FreeImage(PBimageNumber)
  SendMessage_(GadgetID(*boxrect\pbID),#Icon_Rect_Change, drawrect.RECT,0)
EndProcedure

;-Main program
Define hwnd, ImageFile$, image, Quit=0 ; AKJ
UseJPEGImageDecoder()
UsePNGImageDecoder()
If OpenWindow(0, 259, 217, 605, 388, "IconMaker Gadget",  #PB_Window_SystemMenu |  #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  If CreateGadgetList(WindowID(0))
    hwnd = IconGadget(10,40,40,300,300) ; AKJ  Demivec - corrected Gadget# from 40 to 10
    ButtonGadget(1,40,10,90,25,"Open Image") ; AKJ Cater for large fonts
  EndIf
EndIf

;-Event Loop
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1 ; Button gadget
          ImageFile$=OpenFileRequester("Open An Image","","Images|*.bmp;*.jpg;*.png",0)
          If ImageFile$
            image=LoadImage(#PB_Any,ImageFile$)
            SetIconGadgetImage(10,image)
          EndIf
      EndSelect
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
    Case #WM_KEYDOWN ; AKJ See if a key is pressed
      SendMessage_(hwnd, #WM_KEYDOWN, EventwParam(), EventlParam()) ; Relay message
    Case #PB_Event_CloseWindow
      Quit=1
  EndSelect
Until Quit=1

End
New changes as of 18 Feb 2008 (all changes marked in comments with "Demivec -"):

4 lines changed in ScaleImage() by removing hdc related uses and SelectObject_ use

5 lines changed in IconGadget() by replacing rect.RECT with drawrect.Rect as per AKJ's original corrections

6 lines changes in SetIconGadgetImage() by replacing rect.RECT with drawrect.Rect to correct Bug after new image is loaded (change rectangle, load new image, left lick rectangle node, rectangle reverts to one before load)

@Edit: Reverted some code with regard to AKJ's observations and added some Updates to make additional Bug corrections. Explanation added at bottom to reflect this.

Posted: Sun Feb 17, 2008 12:14 pm
by akj
@Demivec

I agree with your change of the icon gadget number as it was indeed a typo by me.

However, I am puzzled by the comments you made about my other bug reports.

In ScaleImage() your final version has:

Code: Select all

hdc=StartDrawing(ImageOutput(newPhoto)) ;AKJ was hdc - Bug?  Demivec -Not a bug 
SelectObject_(newdc,hBitmap)
But now the variable hdc is defined but never used and the variable newdc is used, but never assigned a value. Surely this cannot be correct.

Similarly in IconGadget(), using rect\ rather than drawrect\ introduces a problem in that if the very first thing that is done on running the program is to left-click on a vertex (node) of the selection rectangle, then the latter degenerates to zero size at the top left corner of the icon gadget. This is because the global variable drawrect\ is failing to be initialised correctly.

Did my bug corrections introduce any problems? The program seemed to work OK with them in place.

Posted: Sun Feb 17, 2008 5:09 pm
by localmotion34
akj wrote: But now the variable hdc is defined but never used and the variable newdc is used, but never assigned a value. Surely this cannot be correct.
Sorry about that HDC variable. I reuse the framework of callback procedures for each custom gadget I make, and sometimes the drawing routines I use require a HDC, which i get by using hdc=startdrawing().

I must have overlooked that when i put together this callback. Honestly, I get so tired of having to retype each callback for each message, and all the structures and variables within Wparam and Lparam. So that was just an unnecessary copy and paste bug.


Thanks for you help guys!

Posted: Sun Feb 17, 2008 7:54 pm
by Demivec
akj wrote:@Demivec

I agree with your change of the icon gadget number as it was indeed a typo by me.

However, I am puzzled by the comments you made about my other bug reports.

In ScaleImage() your final version has:

Code: Select all

hdc=StartDrawing(ImageOutput(newPhoto)) ;AKJ was hdc - Bug?  Demivec -Not a bug 
SelectObject_(newdc,hBitmap)
But now the variable hdc is defined but never used and the variable newdc is used, but never assigned a value. Surely this cannot be correct.

Similarly in IconGadget(), using rect\ rather than drawrect\ introduces a problem in that if the very first thing that is done on running the program is to left-click on a vertex (node) of the selection rectangle, then the latter degenerates to zero size at the top left corner of the icon gadget. This is because the global variable drawrect\ is failing to be initialised correctly.

Did my bug corrections introduce any problems? The program seemed to work OK with them in place.
@AKJ: I updated the code in my previous post to reflect the things you mentioned as well as fix an additional Bug. Please refer to that post for the changes.