AmiBroker 6.38.0 RC released

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:


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.

   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.


Nothing "odd" about it. It is the design that we have been using for the web site, forum 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
  // 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");
				case 'E':
					Say("pressed E key");
         switch ( id )
             case idMyFirstButton:
             // do something
				Say( "Pressed first button" );

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


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.

1 Like

Another interesting thing happening:

If I have:


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);

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?


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.


  1. Pretty much everything (including DPI settings) are in the registry:
  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.


Thanks for the suggestion to use GetStatus. As the size of chart pane changes so does info reported by GetStatus. I couldn't find a way to decipher the resolution of the screen, unless Amibroker window is fully maximized.

Perhaps if it make sense, you can add a function that return DPI setting in the future. meanwhile I guest I live with imperfect charts.


Did you remove e-signal Plug-in ? It is not found in 6.38 version.

Esignal Plugin

No, I didn't, but 64-bit Signal plugin uses 2005 runtime and requires you to install runtime separately from:

1 Like

BTW, I believe Esignal will stop providing data access to Amibroker via the eSignal Data Access from December. Anyone else receive the email below? If so, are there other long term historical intraday data providers besides IQFeed?

Email received:
Our records indicate that you are currently subscribed to the eSignal Data Access / eSignal Data Manager product (“Product”).

Please be advised that as of your next monthly billing date of 12/4/2020, the Product will no longer be available under your eSignal account. As of such date, you will no longer receive or be invoiced for the Product.

We apologize for any inconvenience this may cause. We appreciate your business and hope that you will consider transitioning to our [eSignal Suite of software products]

If you have any questions or need further assistance please feel free to [contact our Support Team]

ICE Data Service

I believe that if you change your subscription to regular eSignal, it will continue to work with AmiBroker because, eSignal is using Data Manager and very same API that AmiBroker uses in their own charting application and from technical stand point there is no difference what application consumes data fed by Data Manager.

There is no single technical reason, just purely eSignal "business" decision to "persuade" customers to use their software.

1 Like

Thank you. They switched me over to another service and data is coming back in.

1 Like