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)
64-bit version uses updated VC2017/2019 runtime
64-bit version could produce "Invalid parameter" exception from CRT after backtesting when symbols under test had forbidden characters in them like "%". Fixed
64-bit version: address space layout randomization disabled by /DYNAMICBASE:NO linker option to facilite easier crash location finding
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.
AFL: GetFnData("lastsplitdate") returns empty val instead of zero if last split date is not set
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
AFL: new function Chr( code ) returns string representing single character of given ascii code
AFL: new function GetObject( path, class ) providing functionality equivalent to JScript GetObject and VBScript GetObject
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
AFL: StaticVarAdd when scalar value was added to already existing static var array sometimes random value would appear. Fixed.
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
Analysis: Maximum number of threads per single Analysis window has been increased to 64 (from 32)
Backtester: generation of Buy&Hold stats was not working when "Allow position shrinking" was turned OFF by the user and commission > 0. Fixed
Chart: Data window can now display upto 40 values per single chart pane
Chart: Horizontal line snap to open price (keypress O) or close price (keypress C) was snapping to H-L instead. Fixed
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
IQFeed: improved IQFeed plugin (better support for long EOD histories in mixed mode)
New Analysis: the name of column "contracts/shares" changes each time you change futures mode to prevent confusion among newbies
Plugins: when AFL plugin crashes (throws structured exception) the editor and indicator windows will display call stack for easier debugging of 3rd party plugins
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)
UI: Listview sorting by (single) date column is now 10+ times faster
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)
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
UI: MDI Close/Minimize/Restore buttons are now HighDPI aware
UI: MDI Tab client window buttons are now HighDPI aware
UI: Minimized flicker during docking panes resize by disabling Windows copy bits
UI: Toolbar split-popup buttons are now HighDPI aware
x64 eSignal: reverted to more compatible version compiled with VC2005
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.
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;
}
...
@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)
"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.
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.
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.
@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?
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.
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.