4Misc_StartT4PlatformT@9VersionCheck xHH@Rg(HHdh xHH@Rg(HHdh Layout0xHH@Rg(HHdh LayoutButtonsxHH@Rg(HHdh x HHL Xg(HHdh ^Graph*gWDashSettings#  ! (`2}6Normal@ Lucida Console<HHHH$$4 4 4 4 4 4 qhome=5dC:Users:bruce:Desktop:C:Users:bruce:DesktopIgor_Help_Filese]dC:Program Files:WaveMetrics:Igor Pro 8 Folder:Igor Help Files:C:Program Files:WaveMetrics:Igor Pro 8 Folder:Igor Help FilesRecentWindowsAdvanced Topics.ihfAnalysis.ihfCurve Fitting.ihfDemoLoader.ipfDialog Help.ihfErrors.ihfFatArrowsGetting Started.ihfGraphBrowser.ipfGraphics.ihfIgor Reference.ihf 4Misc_EndTXOPState_StartTHDF5-64\bruce\DesktPeakFunctions2-64T usSutterDAQ-64.ihfErrors.ihfFatXFUNC1-640001000000XMLutils64Graphics.ihff.4XOPState_EndTS_name+L@ UserFrontShowFatArrows() !?U@?͑̀jack????wU=wW}>>Dw>?.?}D?jW?f?r?{?[??{?>t?h?Y?/G?X1?x5?>i>e>Á>>-l>p?F0(?;>?nR?0c? p?bQy?~??F}?ۧv?/l?5^?iL?7??l?2>2>2>lK=虽K޾D $2>" >?B!?,9?M?&_?/ m?@w?r}?&?C_~?6x?HUo?D#b?iQ?k=?Dy&? ?]>:X>6lS>Ķ=!,W@*{}?ʊ>ʊ>؀HarrowState ????@$@b`@$@X@@c@rP@$@X@@$@b`@Z@h @c@rP@Z@h *n#d TXET????"FatArrowsFatArrows#pragma rtGlobals=3 // Use modern global access method and strict wave access. //////////////////////////////////////////////////////////////////////////////////////////////////////// // // 18 December, 2018 // // Hi John, // // I hope this sample experiment will help clarify my question (and Wavemetrics' // answer). I created this experiment by adapting the 'User Draw Shapes' example // experiment included with Igor 8. // // To understand my question, please run the function ShowFatArrows() from the // command window. The FatArrows control panel should appear. Note that each of // the user shapes have b1 (0x02) set in their options field, so each acts like a button. // Therefore when you click on each shape, you'll generate a MouseDown event. // // The function FatArrowFuncBase() prints a line in the history each time the mouse-down // event is detected. Note that each line placed in the history window prints the // index of the arrow (0,1,2,3) which received the mouse-down event and the (x,y) position // clicked. // // Next, please enlarge the FatArrows control panel & note that the arrows adjust size too. // Now using the enlarged panel, please again try to evoke the mouse-down events from each of the arrows. // Note where you must click the control panel to successfully raise the mouse-down events // from each arrow. // // In my tests, I only get mouse-down events when I click over the original (not the resized) // rectangular region. For my project, I need to be able to get mouse events from a rectangular // region that is the same size and in the same position as the enlarged arrow. // // So my question is: How can I programmatically change the size and position of the // rectangular region that raises 'mouse-down' events? I think this is different from the // 'hit testing' you mentioned in your previous comment. // // I hope this makes things more clear. // // Thanks, // Bruce // // Bruce Peters // Sutter Instrument // //////////////////////////////////////////////////////////////////////////////////////////////////////// Static Structure MyFatArrowFuncSettings double headX double shaftY int32 hitMode // 1 if mouse on shaft control point, 2 if on head point EndStructure structure sFatArrow variable x0 variable x1 variable y0 variable y1 endStructure Static Function HitTest(double x, double y, STRUCT PointF &p, STRUCT RectF &r) double slop= 6/(r.right-r.left) // slop from screen coords to normalized object coords return x>(p.h-slop) && x<(p.h+slop) && y>(p.v-slop) && y<(p.v+slop) End Static Function clip(double val, double minVal, double maxVal) if( val maxVal ) return maxVal endif return val End function SetArrowState (struct sFatArrow &thisFatArrow, struct pointf &pnlSize, int arrowIndex) variable arrowWidth = (pnlSize.h - 3*UIMARGIN_PIXELS)/2 variable arrowHeight = (pnlSize.v - 3*UIMARGIN_PIXELS)/2 int rowNum = arrowIndex/2 int colNum = mod (arrowIndex, 2) thisFatArrow.x0 = (colNum+1)*UIMARGIN_PIXELS + colNum*arrowWidth thisFatArrow.y0 = (rowNum+1)*UIMARGIN_PIXELS + rowNum*arrowheight thisFatArrow.x1 = thisFatArrow.x0 + arrowWidth + 1 thisFatArrow.y1 = thisFatArrow.y0 + arrowHeight + 1 end function HookProc_FatArrow(STRUCT WMWinHookStruct &s) string hostPnlName = s.winName wave arrowState struct sFatArrow thisFatArrow struct pointf pnlSize switch (s.eventCode) case 6: // pnl resize event GetWindow $hostPnlName, wsizeDC pnlSize.h = V_right - V_left + 1 pnlSize.v = V_bottom - V_top + 1 int i for (i=0; i<4; i++) StructGet thisFatArrow, arrowState[i] SetArrowState (thisFatArrow, pnlSize, i) // adjust arrow specs <=> new panel size StructPut thisFatArrow, arrowState[i] endfor break default: break endswitch return 0 end Static Function FatArrowFuncBase(STRUCT WMDrawUserShapeStruct &s, Variable rotation, int myIndex) // rotation is degrees but only 0, 90, 180 and -90 supported STRUCT MyFatArrowFuncSettings fs struct sFatArrow thisFatArrow wave arrowState variable pixelsPerPoint = screenresolution/72 if( strlen(s.privateString) != 0 ) StructGet/S fs,s.privateString else fs.headX= 0.6 fs.shaftY= 0.2 // offset from center endif // Start of poly defining arrow double originX= 0 double originY= 0.5-fs.shaftY // Location of shaft control point double shaftX= 0 double shaftY= 0.5 + fs.shaftY // Location of head control point double headX= fs.headX double headY= 1.0 structGet thisFatArrow, arrowState[myIndex] variable origXabs = thisFatArrow.x0 variable origYabs = thisFatArrow.y0 variable arrowWidth = (thisFatArrow.x1 - thisFatArrow.x0 + 1) variable arrowHeight = (thisFatArrow.y1 - thisFatArrow.y0 + 1) Make/FREE polyX={originX, headX, headX, 1, headX, headX, originX, originX} Make/FREE polyY={originY, originY, 0, 0.5, 1, shaftY, shaftY, originY} if( rotation == 180 ) originX= 1 - originX shaftX= 1 - shaftX headX= 1 - headX polyX= 1-polyX elseif( rotation == 90 || rotation == -90 ) double tmp= originX originX= originY originY= tmp tmp= shaftX shaftX= shaftY shaftY= tmp tmp= headX headX= headY headY= tmp Duplicate/FREE polyX, polyXtmp polyX= polyY polyY= polyXtmp if( rotation == 90 ) originY= 1 - originY shaftY= 1 - shaftY headY= 1 - headY polyY= 1-polyY endif endif Variable rval= 1 StrSwitch(s.action) case "draw": // scale up the relative points in polyX & polyY polyX *= arrowWidth polyY *= arrowHeight // scale & displace the origin's coordinates too originX *= arrowWidth originX += origXabs originY *= arrowHeight originY += origYabs setdrawenv xcoord=abs, ycoord=abs DrawPoly/ABS originX,originY,1,1,polyX,polyY // draw the polygon for the arrow if( strlen(s.textString) != 0 ) SetDrawEnv textxjust=1, textyjust=1, textrot= s.angle DrawText 0.5,0.5, s.textString // draw text centered within the 'hot rectangle' endif break case "drawSelected": DrawPoly/ABS originX,originY,1,1,polyX,polyY SetDrawEnv fillfgc= (65535,65535,0),fillpat=1,linethick=1,save SetDrawEnv push SetDrawEnv origin= shaftX, shaftY SetDrawEnv xcoord=abs,ycoord=abs DrawOval -5,-5,5,5 SetDrawEnv pop SetDrawEnv push SetDrawEnv origin= headX, headY SetDrawEnv xcoord=abs,ycoord=abs DrawOval -5,-5,5,5 SetDrawEnv pop break case "hitTest": break case "mouseDown": printf "mouseDown: index=%d\t s.mouseLoc.h=%g\t, s.mouseLoc.v=%g\n", myIndex, s.mouseLoc.h, s.mouseLoc.v if( HitTest(headX,headY, s.mouseLoc,s.objectR) ) fs.hitMode= 1 s.doSetCursor= 1 s.cursorCode= 5 elseif( HitTest(shaftX, shaftY ,s.mouseLoc,s.objectR) ) fs.hitMode= 2 s.doSetCursor= 1 s.cursorCode= 6 else fs.hitMode= 0 endif break case "mouseMove": if( fs.hitMode == 1 ) if( rotation == 90 || rotation == -90 ) fs.headX= clip( rotation == 90 ? 1-s.mouseLoc.v : s.mouseLoc.v,0,1); else fs.headX= clip( rotation == 180 ? 1 - s.mouseLoc.h : s.mouseLoc.h,0,1); endif elseif( fs.hitMode == 2 ) if( rotation == 90 || rotation == -90 ) fs.shaftY= clip( s.mouseLoc.h, 0.5, 1) - 0.5; else fs.shaftY= clip( s.mouseLoc.v, 0.5, 1) - 0.5 endif endif break case "mouseUp": break // don't care about this one default: break EndSwitch StructPut/S fs,s.privateString return rval end Function MyFatArrowFuncExR(STRUCT WMDrawUserShapeStruct &s) : DrawUserShape int myIndex = str2num(s.textString) struct sFatArrow thisFatArrow wave arrowState if( CmpStr(s.action, "getInfo") == 0 ) s.textString= "Arrows" s.privateString= "Right Arrow" s.options = s.options | 0x02 return 1 endif return FatArrowFuncBase(s, 0, myIndex) End Function MyFatArrowFuncExU(STRUCT WMDrawUserShapeStruct &s) : DrawUserShape int myIndex = str2num(s.textString) if( CmpStr(s.action, "getInfo") == 0 ) s.textString= "Arrows" s.privateString= "Up Arrow" s.options = s.options | 0x02 return 1 endif return FatArrowFuncBase(s, 90, myIndex) End Function MyFatArrowFuncExL(STRUCT WMDrawUserShapeStruct &s) : DrawUserShape int myIndex = str2num(s.textString) if( CmpStr(s.action, "getInfo") == 0 ) s.textString= "Arrows" s.privateString= "Left Arrow" s.options = s.options | 0x02 return 1 endif return FatArrowFuncBase(s, 180, myIndex) End Function MyFatArrowFuncExD(STRUCT WMDrawUserShapeStruct &s) : DrawUserShape int myIndex = str2num(s.textString) if( CmpStr(s.action, "getInfo") == 0 ) s.textString= "Arrows" s.privateString= "Down Arrow" s.options = s.options | 0x02 return 1 endif return FatArrowFuncBase(s, -90, myIndex) End // Platform=WindowsNT, IGORVersion=8.020, architecture=Intel, systemTextEncoding="Windows-1252", historyTextEncoding="MacRoman", procwinTextEncoding="MacRoman", recreationTextEncoding="MacRoman", build=32405 #pragma TextEncoding = "MacRoman" Silent 101 // use | as bitwise or -- not comment. NewPath/Z Igor_Help_Files "::::Program Files:WaveMetrics:Igor Pro 8 Folder:Igor Help Files:" DefaultFont "Arial" MoveWindow/C 13.5,515,270,656.75 String/G root:gWMSetNextTextFilesTextEncoding = "MacRoman" // Text encoding for "FatArrows". Used by Igor Pro 7. OpenProc/W=(291.75,40.25,984,619.25)/J=5842 "FatArrows" MoveWindow/P 96,40.25,893.25,561.5 KillStrings/Z root:gWMSetNextTextFilesTextEncoding #pragma rtGlobals=3 // Use modern global access method and strict wave access. //////////////////////////////////////////////////////////////////////////////////////////////////////// // // 18 December, 2018 // // Hi John, // // I hope this sample experiment will help clarify my question (and Wavemetrics' // answer). I created this experiment by adapting the 'User Draw Shapes' example // experiment included with Igor 8. // // To understand my question, please run the function ShowFatArrows() from the // command window. The FatArrows control panel should appear. Note that each of // the user shapes have b1 (0x02) set in their options field, so each acts like a button. // Therefore when you click on each shape, you'll generate a MouseDown event. // // The function FatArrowFuncBase() prints a line in the history each time the mouse-down // event is detected. Note that each line placed in the history window prints the // index of the arrow (0,1,2,3) which received the mouse-down event and the (x,y) position // clicked. // // Next, please enlarge the FatArrows control panel & note that the arrows adjust size too. // Now using the enlarged panel, please again try to evoke the mouse-down events from each of the arrows. // Note where you must click the control panel to successfully raise the mouse-down events // from each arrow. // // In my tests, I only get mouse-down events when I click over the original (not the resized) // rectangular region. For my project, I need to be able to get mouse events from a rectangular // region that is the same size and in the same position as the enlarged arrow. // // So my question is: How can I programmatically change the size and position of the // rectangular region that raises 'mouse-down' events? I think this is different from the // 'hit testing' you mentioned in your previous comment. // // I hope this makes things more clear. // // Thanks, // Bruce // // Bruce Peters // Sutter Instrument // //////////////////////////////////////////////////////////////////////////////////////////////////////// constant UIMARGIN_PIXELS = 10 function ShowFatArrows() DoWindow PanelFatArrows if( V_Flag == 0 ) PanelFatArrows() endif end function PanelFatArrows() struct pointf pnlSize struct pointf pnlOrigin struct sFatArrow thisFatArrow make /O /N=(4,4) arrowState pnlOrigin.h = 100 pnlOrigin.v = 100 pnlSize.h = 300 pnlSize.v = 200 NewPanel /N=FatArrows /W=(pnlOrigin.h, pnlOrigin.v, pnlOrigin.h+pnlSize.h+1, pnlOrigin.v+pnlSize.v+1) SetDrawLayer UserBack SetArrowState (thisFatArrow, pnlSize, 0) DrawUserShape thisFatArrow.x0, thisFatArrow.y0, thisFatArrow.x1,thisFatArrow.y1, MyFatArrowFuncExR, "0", A"5MuMAz5K\\>=z!!!!\"" structPut thisFatArrow, arrowState[0] SetArrowState (thisFatArrow, pnlSize, 1) DrawUserShape thisFatArrow.x0, thisFatArrow.y0, thisFatArrow.x1,thisFatArrow.y1, MyFatArrowFuncExL, "1", A"5M[,E^]4?75L**WJ,fQLz" structPut thisFatArrow, arrowState[1] SetArrowState (thisFatArrow, pnlSize, 2) DrawUserShape thisFatArrow.x0, thisFatArrow.y0, thisFatArrow.x1,thisFatArrow.y1, MyFatArrowFuncExU, "2", A"5MV7>^]4?75KY5]J,fQLz" structPut thisFatArrow, arrowState[2] SetArrowState (thisFatArrow, pnlSize, 3) DrawUserShape thisFatArrow.x0, thisFatArrow.y0, thisFatArrow.x1,thisFatArrow.y1, MyFatArrowFuncExD, "3", A"5Mh+X?iU0,5KPfXJ,fQLz" structPut thisFatArrow, arrowState[3] SetWindow FatArrows hook(FatArrowHook)=HookProc_FatArrow // Add a hook function to the panel so we can respond to resize events End