AmiBroker 6.38.0 RC released

A new release candidate version (6.38.0) of AmiBroker is available now.

DOWNLOAD LINKS

32-bit version:
http://www.amibroker.com/members/download.php?AmiBroker6380.exe
(10 300 856 bytes)

64-bit version:
http://www.amibroker.com/members/download.php?AmiBroker6380x64.exe
(11 022 304 bytes)

DOCUMENTATION

DevLog announcement: http://www.amibroker.com/devlog/2020/10/15/amibroker-6-38-0-rc-released/

For the details see ReadMe.html and ReleaseNotes.html inside AmiBroker folder.

UPGRADE POLICY

This version is a free upgrade only for users who registered AmiBroker after October 15, 2018 . Users who registered earlier, would need to purchase license upgrade. To find out the version you currently have use Account Information page at http://www.amibroker.com/members/info.php

CHANGES FOR VERSION 6.38.0 (as compared to 6.35.1)

  1. 64-bit version uses updated VC2017/2019 runtime
  2. 64-bit version could produce "Invalid parameter" exception from CRT after backtesting when symbols under test had forbidden characters in them like "%". Fixed
  3. 64-bit version: address space layout randomization disabled by /DYNAMICBASE:NO linker option to facilite easier crash location finding
  4. AFL: assignment new matrix value to a variable already holding matrix value did not immediately free memory (at the time of assignment). This memory was only freed at the end of the formula. Now it is freed earlier (at assignment) to lower memory usage.
  5. AFL: GetFnData("lastsplitdate") returns empty val instead of zero if last split date is not set
  6. AFL: GfxDrawImage with PNG file could fail if very same file was accessed simultaneously from multiple threads due to "no-sharing" mode that 3rd party XTP lib used. Fixed by using shareDenyWrite
  7. AFL: new function Chr( code ) returns string representing single character of given ascii code
  8. AFL: new function GetObject( path, class ) providing functionality equivalent to JScript GetObject and VBScript GetObject
  9. AFL: new function GuiSendKeyEvents("ED") - register given characters to be sent as Gui event when keyboard key is pressed. GuiGetEvent will return code == notifyKeyDown and id of given character, for example id == 'D' for D letter
  10. AFL: StaticVarAdd when scalar value was added to already existing static var array sometimes random value would appear. Fixed.
  11. AFL: when file creation or modication date was exact midnight fgetstatus() returned datetime indicating "eod mark" (date without time), now it gives 00:00:00
  12. Analysis: Maximum number of threads per single Analysis window has been increased to 64 (from 32)
  13. Backtester: generation of Buy&Hold stats was not working when "Allow position shrinking" was turned OFF by the user and commission > 0. Fixed
  14. Chart: Data window can now display upto 40 values per single chart pane
  15. Chart: Horizontal line snap to open price (keypress O) or close price (keypress C) was snapping to H-L instead. Fixed
  16. Charts: Snap to price - the meaning of threshold is changed - instead of % of price it now means % of chart height. So 5% will snap within +/-5 of chart height. This allows it to work universally across different securities (stocks/forex) and different zo
  17. IQFeed: improved IQFeed plugin (better support for long EOD histories in mixed mode)
  18. New Analysis: the name of column "contracts/shares" changes each time you change futures mode to prevent confusion among newbies
  19. Plugins: when AFL plugin crashes (throws structured exception) the editor and indicator windows will display call stack for easier debugging of 3rd party plugins
  20. UI: Dialog boxes are moved back main display screen if multi-monitor configuration was changed and multi-monitor setup is not rectangular (for example monitors of different sizes)
  21. UI: Listview sorting by (single) date column is now 10+ times faster
  22. UI: Listview uses non optimized parsing for str to date conversion for date formats that include names of the months instead of numbers (avoids problems with different names of months in different languages)
  23. UI: Main window and AFL Editor frame is moved back to (0,0) if multi-monitor configuration was changed and multi-monitor setup is not rectangular (for example monitors of different sizes), so saved position falls outside currently available working area
  24. UI: MDI Close/Minimize/Restore buttons are now HighDPI aware
  25. UI: MDI Tab client window buttons are now HighDPI aware
  26. UI: Minimized flicker during docking panes resize by disabling Windows copy bits
  27. UI: Toolbar split-popup buttons are now HighDPI aware
  28. x64 eSignal: reverted to more compatible version compiled with VC2005
23 Likes

Hi Tomasz,

Thank you for the release.

I just showed you my support by putting money where my mouth is. I have paid and upgraded Amibroker to this latest professional version.

2 Likes

Looks really great - thank you.

1 Like

Upgraded just now. I have been waiting since a long time.Thank you.

Why the Letter "A" is not capitalized in Amibroker Logo? Just sharing because it is looking odd.Amib

Thanks so much for GuiSendKeyEvents(). I'm already making changes to my code now and it will definitely help me in trading fast intraday futures charts. I have a whole panel of Gui buttons to press for various trade setups and it's quicker to press 2-3 keys in a row than hunt and click the buttons with a mouse.

1 Like

Just a reminder to others looking into using GuiSendKeyEvents(). If you use a switch statement on the id returned from the GetGuiEvent(), realize that the key code coming back (e.g., 'S' is an integer 83 equivalent in the ASCII table) could overlap your id's that you setup for your Gui Controls and you can end up executing unrelated parts of your code vs. the logic you think you coded correctly.

So, if I had code like the:


GuiSendKeyEvents("LS");

idLong = 83;
idShort = 84;

for (i = 0; id = GuiGetEvent(i, 0); i++) // get the id of the event
{
  switch (id) {
    case idLong:
    case 'L':
        // OOPS!  User pressed the 'S' key but this code case executed
        // because 'S' is 83 in the ASCII table and that coincides what
        // integer I assigned the "Long" Gui button to.
    break;

   case idShort:
   case 'S':
       // process this code section by either pressing the "Short"
       // Gui button or by pressing the 'S' key.   This case will not 
       // be executed if the user pressed the 'S' key.
   break;
}
...

2 Likes

Nothing "odd" about it. It is the design that we have been using for the web site http://www.amibroker.com/, forum https://forum.amibroker.com and program itself for at least 3 years.

1 Like

@SteveH with regards to GuiSendKeyEvents and potential overlap:

There is no overlap problem if you have correct code, you should be checking not only the ID, but also notification code/type.

In other words, to detect key down events, you have to include this part in your formula:

id = GuiGetEvent( n, 0 ); // this gets the ID of control, or ASCII code of key
code = GuiGetEvent( n, 1 ); // this gets notification CODE

if( code == notifyKeyDown )
{
   // this is KEY DOWN event
   // id holds ASCII code of the key
}
else
{
  // this is OTHER event (you can extend detection to click/setfocus/etc)
  // id holds control ID
}

Example coding that checks properly various events:

idMyFirstButton = 1;
idMySecondButton = 2;

function CreateGUI()
{
     GuiSendKeyEvents("ED"); // send notifications for keypresses of "E" and "D"
     GuiButton( "Enable", idMyFirstButton, 10, 60, 100, 30, notifyClicked );
     GuiButton( "Disable", idMySecondButton, 110, 60, 100, 30, notifyClicked );
}

function HandleEvents()
{
    for ( n = 0; id = GuiGetEvent( n, 0 ); n++ ) // get the id of the event
    {
         code = GuiGetEvent( n, 1 );

		 if( code == notifyKeyDown )
		 {
			switch( id )
			{
				case 'D': 
					Say("pressed D key");
					break;
		 
				case 'E':
					Say("pressed E key");
					break;
			}
		 }
		 else
         switch ( id )
         {
             case idMyFirstButton:
             // do something
				Say( "Pressed first button" );
                break;

             case idMySecondButton:
             // do something else
				Say( "Pressed second button" );
                break;

             default:
                 break;
         }
     }
}
CreateGUI();
HandleEvents();

Alternatively, you can use "high" values for control IDs that don't overlap with the ASCII table (>=256)

7 Likes

"Alternatively, you can use "high" values for control IDs that don't overlap with the ASCII table (>=256)"

Yes, I started out the same as your code separation example based on the notify but the letters and buttons turned out to have too much code in common since the letters are shortcuts for the button presses.

Both ways might deserve mention in the GetGuiEvent() documentation.

1 Like

Another interesting thing happening:

If I have:

GuiSendKeyEvents("12")

I have some code in a switch statement in the typical for() loop getting Gui events:

case idQty:
  if (notify == notifyEditChange)
  {
	str = GuiGetText(idQty);
	if (_market_position == positionFlat)
		_pos = StrToNum(str);
  }
break;

So if I'm in the GuiEdit control (i.e., the edit control that idQty is tied to has the focus), trying to type in the number 1 or 2, they got "eaten" by the notifyKeyDown event and won't be accepted into the edit box.

Sorry, but that how Windows works. Only one window receives events. If keys were not eaten by PARENT, they would not work if focus was on buttons. So in order to handle key strokes when you have GUI controls and you may have focus on GUI control, the PARENT has to eat them. And edit fields are children as buttons.
That is exactly what I described earlier:

If I change that so parent does not eat keystrokes, they notifyKeyDown will not work when focus is in any control (which in practice means after any click on any control)

One solution is NOT to register digit keys via GuiSendKeyEvents. Only characters that are registered are eaten. So if you don't register digits for key down notifications via GuiSendKeyEvents, they will be able to arrive to the edit field.

1 Like

Thanks for taking the time to explain this.

From a logical level, I would have thought that if any of the script's edit controls has the focus, the GuiSendKeyEvents() processing logic would not be executed. Essentially, it's turned off. However, if no edit control has the focus then GuiSendKeyEvents() logic can be active (turned on).

Another thing I'm noticing is that the keystrokes detected by GuiSendKeyEvents() are raw. For example, there's no such thing as GuiSendKeyEvents("@"), even though its in the ASCII table and has its own integer equivalent. That's a shift-2 on a US keyboard. It's up the user to also call the GetAsyncKeyState() function to do the proper detection.

Yes, as name says notifyKeyDown captures WM_KEYDOWN Windows messages:

and yes WM_KEYDOWN are raw.

Key codes sent in WM_KEYDOWN are listed here:

With regards to focus - I explained already two times -please re-read carefully
the previous post and post that I quoted. I can only re-iterate:

and we would be back to square one (situation from: Any interest in event-driven keypresses?)

1 Like

@Tomasz, Thank you for the release. I use 4k monitors, the HighDPI awareness fixes MDI issues you pointed out in 23 & 24. I wrote a bunch of chart using gfx. When I wrote those I was using 1920x1080 resolution monitors. They look perfect on 1920x1080 monitors, however on 4k monitors I think because of pixel size they don't look as good. Does gfx need to become HighDPI aware or is there a programming trick that can be use to make gfx charts resolution independent?

2 Likes

I assume that you mean Gfx* functions when you talk about "chart using gfx". If thats the case, all Gfx* works with physical pixels, that obviously are much smaller on HighDPI screens.
Therefore you need to scale all pixel co-ordinates if you want Gfx* - drawn elements to be larger. Program won't do that for you because, as I wrote, the unit for Gfx function is one physical pixel.

Thanks, I was referring to Gfx functions. Is there a function (a way) to get the resolution of the screen in afl. I am thinking using conditional statement for scaling co-ordinates based on screen resolution.

There is only GetStatus("pxchartwidth"), GetStatus("pxchartheight") that reports CHART pane pixel dimensions. You may use that to switch after certain threshold is exceeded.

Notes:

  1. Pretty much everything (including DPI settings) are in the registry:
    https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/dpi-related-apis-and-registry-settings
  2. In Windows 10 you can have multiple monitors EACH having different DPI
1 Like

A question to the community here. One of the features in the latest release is this;

  1. AFL: new function GetObject( path, class ) providing functionality equivalent to JScript GetObject and VBScript GetObject

It sounds like a useful and flexible feature. What are some useful possible applications for this feature?

GetObject allows you to connect to already running instance of OLE automation server that has given file already opened:

// would connect to running Excel instance that has given file open
obj = GetObject("C:\\SomeDir\\TestFile.XLS");  

Disclaimer: this function uses pretty old Microsoft APIs that are known to have their own bag of problems and are known to NOT work for some automation objects on Windows 10. I don't accept ANY "bug reports" to the functionality of GetObject, because it is SOLELY MICROSOFT code and I can't fix Microsoft errors.

2 Likes