Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Change Monitor Input Source


  • Please log in to reply
21 replies to this topic
lifeweaver
  • Members
  • 868 posts
  • Last active: Jan 25 2016 01:29 AM
  • Joined: 04 Mar 2013

I wasn't able to find a good topic on how to change my monitor's input source with AutoHotkey so here it is, I got a lot of help from some already posted topics:

  • How to get the physical monitor handle here from Solar.
  • List of VCP Control codes here i.e. the input control code is 0x60
  • dxva2.dll for the functions, documentation in msdn here.

I actually used the GetVCPFeatureAndVCPFeatureReply function to see what values I would need to set the Input value to i.e.

 

I found for the Asus vg236 the codes where

  • DVI = 3
  • HDMI = 4
  • YPbPr = 12

Code

; Finds monitor handle
getMonitorHandle()
{
  ; Initialize Monitor handle
  hMon := DllCall("MonitorFromPoint"
    , "int64", 0 ; point on monitor
    , "uint", 1) ; flag to return primary monitor on failure

    
  ; Get Physical Monitor from handle
  VarSetCapacity(Physical_Monitor, 8 + 256, 0)

  DllCall("dxva2\GetPhysicalMonitorsFromHMONITOR"
    , "int", hMon   ; monitor handle
    , "uint", 1   ; monitor array size
    , "int", &Physical_Monitor)   ; point to array with monitor

  return hPhysMon := NumGet(Physical_Monitor)
}

destroyMonitorHandle(handle)
{
  DllCall("dxva2\DestroyPhysicalMonitor", "int", handle)
}

getMonitorInputSource()
{
  handle := getMonitorHandle()
  DllCall("dxva2\GetVCPFeatureAndVCPFeatureReply"
    , "int", handle
    , "char", 0x60 ;VCP code for Input Source Select
    , "Ptr", 0
    , "uint*", currentValue
    , "uint*", maximumValue)
  destroyMonitorHandle(handle)
  return currentValue
}

: Used to set the monitor source, I do not know what happens if you send it a value higher than the maximum.
setMonitorInputSource(source)
{
  handle := getMonitorHandle()
  DllCall("dxva2\SetVCPFeature"
    , "int", handle
    , "char", 0x60 ;VCP code for Input Source Select
    , "uint", source)
  destroyMonitorHandle(handle)
}  

; Msgbox with current monitor input source
!r::
msgbox % getMonitorSource()
return

So to set the monitor input source to HDMI I would do setMonitorSource(4), I'm sure you could pretty this up a bit all into one function.

 

Edit:

 

Here is what I ended up using:

; Finds monitor handle
getMonitorHandle()
{
  ; Initialize Monitor handle
  hMon := DllCall("MonitorFromPoint"
    , "int64", 0 ; point on monitor
    , "uint", 1) ; flag to return primary monitor on failure

    
  ; Get Physical Monitor from handle
  VarSetCapacity(Physical_Monitor, 8 + 256, 0)

  DllCall("dxva2\GetPhysicalMonitorsFromHMONITOR"
    , "int", hMon   ; monitor handle
    , "uint", 1   ; monitor array size
    , "int", &Physical_Monitor)   ; point to array with monitor

  return hPhysMon := NumGet(Physical_Monitor)
}

destroyMonitorHandle(handle)
{
  DllCall("dxva2\DestroyPhysicalMonitor", "int", handle)
}

; Used to change the monitor source
; DVI = 3
; HDMI = 4
; YPbPr = 12
setMonitorInputSource(source)
{
  handle := getMonitorHandle()
  DllCall("dxva2\SetVCPFeature"
    , "int", handle
    , "char", 0x60 ;VCP code for Input Source Select
    , "uint", source)
  destroyMonitorHandle(handle)
}

; Gets Monitor source
getMonitorInputSource()
{
  handle := getMonitorHandle()
  DllCall("dxva2\GetVCPFeatureAndVCPFeatureReply"
    , "int", handle
    , "char", 0x60 ;VCP code for Input Source Select
    , "Ptr", 0
    , "uint*", currentValue
    , "uint*", maximumValue)
  destroyMonitorHandle(handle)
  return currentValue
}

#IfWinActive
Pause::
if(getMonitorInputSource() < 2)
  setMonitorInputSource(3)
else
  setMonitorInputSource(12)
return

Edited by lifeweaver, 02 September 2013 - 02:29 PM.

My script runs in A_AhkVersion:=1.1.22.07, get the latest version at http://ahkscript.org/download/

Check out this AutoHotkey tutorial: http://ahkscript.git...o/AHK_Tutorial/

Read the documentation: http://ahkscript.org.../AutoHotkey.htm


gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
Very cool, i never woulda guessed that was even possible... Thanks for sharing i cant wait to try it out

Larctic
  • Members
  • 303 posts
  • Last active: May 10 2016 04:56 PM
  • Joined: 21 Jul 2012

How to change the display color temperature it? Like f.lux that.



lifeweaver
  • Members
  • 868 posts
  • Last active: Jan 25 2016 01:29 AM
  • Joined: 04 Mar 2013

Thanks,
 
This is still a work in progress though, it does change the monitor input source, however after that the monitor doesn't detect the source on that input so I'm still looking to see if I need to set another VCP code to make it look for input.
 
@ Larctic: I'd imagine you want to using the SetMonitorColorTemperature function in the same dll and use GetMonitorColorTemperature function to check that it changed, however both of these functions use a type  'MC_COLOR_TEMPERATURE' and I have no idea how that would translate to AutoHotkey.
 
I think it should return a value similar to these but I don't know:

typedef enum _MC_COLOR_TEMPERATURE {
  MC_COLOR_TEMPERATURE_UNKNOWN,
  MC_COLOR_TEMPERATURE_4000K,
  MC_COLOR_TEMPERATURE_5000K,
  MC_COLOR_TEMPERATURE_6500K,
  MC_COLOR_TEMPERATURE_7500K,
  MC_COLOR_TEMPERATURE_8200K,
  MC_COLOR_TEMPERATURE_9300K,
  MC_COLOR_TEMPERATURE_10000K,
  MC_COLOR_TEMPERATURE_11500K 
} MC_COLOR_TEMPERATURE, *LPMC_COLOR_TEMPERATURE;

Something like this doesn't work though:

  DllCall("dxva2\GetMonitorColorTemperature"
    , "int", handle
    , "float*", test)

msgbox % test

I'm hopping someone with an understanding of dllcall can help out.

 

EDIT: After a little googling looks like this works to get the color temerature.

DllCall("dxva2\GetMonitorColorTemperature"
    , "int", handle
    , "char*", test)

; My colors, which correlate to the _MC_COLOR_TEMPERATURE above 
; Warm   = 2 = MC_COLOR_TEMPERATURE_5000K
; Normal = 3 = MC_COLOR_TEMPERATURE_6500K
; Cool   = 6 = MC_COLOR_TEMPERATURE_9300K
; User   = 0 = MC_COLOR_TEMPERATURE_UNKNOWN

I tried this before but since I'm in 'user' mode it returns a zero so I was thinking it wasn't working! lol


Edited by lifeweaver, 01 September 2013 - 04:22 PM.

My script runs in A_AhkVersion:=1.1.22.07, get the latest version at http://ahkscript.org/download/

Check out this AutoHotkey tutorial: http://ahkscript.git...o/AHK_Tutorial/

Read the documentation: http://ahkscript.org.../AutoHotkey.htm


lifeweaver
  • Members
  • 868 posts
  • Last active: Jan 25 2016 01:29 AM
  • Joined: 04 Mar 2013
@Larctic
Looks like you could use/set the monitor's preset temperatures with the SetVCPFeature function:
 
I used the GetVCPFeatureAndVCPFeatureReply function to find out the values of my monitor:
5000k = 4
6500k = 5
9300k = 8
A utility you might try to figure out the actual numbers is softMCCS, looks something like this
h2vLvM8.png

My script runs in A_AhkVersion:=1.1.22.07, get the latest version at http://ahkscript.org/download/

Check out this AutoHotkey tutorial: http://ahkscript.git...o/AHK_Tutorial/

Read the documentation: http://ahkscript.org.../AutoHotkey.htm


Larctic
  • Members
  • 303 posts
  • Last active: May 10 2016 04:56 PM
  • Joined: 21 Jul 2012
Thanks for your help
f.lux is the software I use regularly, I've always wanted to use AHK replace it.
Can you help me write an example?
Read and set the color temperature.
Because I do not know how to use DllCall, no programming foundation.


lifeweaver
  • Members
  • 868 posts
  • Last active: Jan 25 2016 01:29 AM
  • Joined: 04 Mar 2013

I don't think I have the knowledge on how to help you, I would set a support topic on the subject "How do I set my monitor's Color Temperature",

 

One thing you might do is check out this post on DllCall's.

 

I don't know how to do it like f.lux as f.lux lets you change the color temperature through the entire range, I think the SetMonitorColorTemperature function would limit you to 4000K, 5000K, 6500K, 7500K, 8200K, 9300K, 10000K, or 11500K.

 

You could try to set the 0x14 different values but again that limits you to the presets, right now I'm focused on the 0x0B as it seems to hold interesting values see:

; Finds monitor handle
getMonitorHandle()
{
  ; Initialize Monitor handle
  hMon := DllCall("MonitorFromPoint"
    , "int64", 0 ; point on monitor
    , "uint", 1) ; flag to return primary monitor on failure

    
  ; Get Physical Monitor from handle
  VarSetCapacity(Physical_Monitor, 8 + 256, 0)

  DllCall("dxva2\GetPhysicalMonitorsFromHMONITOR"
    , "int", hMon   ; monitor handle
    , "uint", 1   ; monitor array size
    , "int", &Physical_Monitor)   ; point to array with monitor

  return hPhysMon := NumGet(Physical_Monitor)
}

destroyMonitorHandle(handle)
{
  DllCall("dxva2\DestroyPhysicalMonitor", "int", handle)
}

handle := getMonitorHandle()

DllCall("dxva2\GetVCPFeatureAndVCPFeatureReply"
  , "int", handle
  , "char", 0x0B
  , "Ptr", 0
  , "uint*", currentValue
  , "uint*", maximumValue)
    
destroyMonitorHandle(handle)

However, if you test the above with f.lux and change the temperature you notice the values don't change so there must be some way to change the temperature where your not actually changing the values in the Monitor VCP table but some other way.


My script runs in A_AhkVersion:=1.1.22.07, get the latest version at http://ahkscript.org/download/

Check out this AutoHotkey tutorial: http://ahkscript.git...o/AHK_Tutorial/

Read the documentation: http://ahkscript.org.../AutoHotkey.htm


Larctic
  • Members
  • 303 posts
  • Last active: May 10 2016 04:56 PM
  • Joined: 21 Jul 2012
Yes, after the test, the script has no effect.
I modified some value, but also to no avail.
I think I should learn to use DllCall.
In order to find out the real solution.
 
Very grateful for your help.happy.png


Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
Interesting. Thanks for posting it. I have a few random observations/pointers:

Each time you "get" the handle, the API allocates some resources. You need to call DestroyPhysicalMonitors when you're done with the handle, or at least don't "get" the handle repeatedly (just once, then reuse it).

Your Physical_Monitor structure is too small: the szPhysicalMonitorDescription field is 128 wide characters, so 256 bytes.

You've used (A_PtrSize ? A_PtrSize : 4) presumably so that it will work on old AutoHotkey versions, where A_PtrSize is not defined. However, those versions also don't support "ptr", which you have used unconditionally in one of your functions. You may as well just use A_PtrSize, or easier, 8. At worst, it seems like a waste of 4 bytes; but actually, the memory usage is lower because the expression is smaller.

I don't know under what conditions GetNumberOfPhysicalMonitorsFromHMONITOR returns more than 1, but if that happens, your function will not handle it well, since you are only allocating one PHYSICAL_MONITOR structure. There's no point in calling GetNumberOfPhysicalMonitorsFromHMONITOR anyway; just pass nMon:=1 to GetPhysicalMonitorsFromHMONITOR.

"0x60" is semantically incorrect, and inefficient. When you want a hexadecimal number, write without quotes: 0x60.

lifeweaver
  • Members
  • 868 posts
  • Last active: Jan 25 2016 01:29 AM
  • Joined: 04 Mar 2013

Thanks Lexikos,

 

I appreciate the pointers, what you see is what I know about DllCall, not much!

 

I've updated the original post.


My script runs in A_AhkVersion:=1.1.22.07, get the latest version at http://ahkscript.org/download/

Check out this AutoHotkey tutorial: http://ahkscript.git...o/AHK_Tutorial/

Read the documentation: http://ahkscript.org.../AutoHotkey.htm


nepter
  • Members
  • 53 posts
  • Last active: Jul 31 2016 06:47 AM
  • Joined: 29 Jun 2012

 

Yes, after the test, the script has no effect.

The script runs above windows vista.



Larctic
  • Members
  • 303 posts
  • Last active: May 10 2016 04:56 PM
  • Joined: 21 Jul 2012

The script runs above windows vista.

 

My system is WIN7 64, I think it was for other reasons. Thanks.



XX0
  • Members
  • 32 posts
  • Last active: Dec 12 2014 01:05 PM
  • Joined: 17 Jul 2010

This really has potential to become a full replacement of the monitor's OSD.

 

Using VCP code 0xd6, with in my case a set of {1, 4, 5} values, I was able to turn on, standby or turn off my monitor. Though after turning it on, the input source was undefined and setting it using the script didn't work while it did before. Hopefully that's just a quirk of my monitor because when hooking up a TV as a HTPC, turning it on, setting the input and turning it off this way, without a remote, would be pretty cool.

 

Also, as a dual screen user, multi monitor support would be nice. I don't know if that is hard to implement, because I'm just now starting to look into it.



lifeweaver
  • Members
  • 868 posts
  • Last active: Jan 25 2016 01:29 AM
  • Joined: 04 Mar 2013

From what I've read certain monitors support or react to VCP codes in different ways things like manufacturer/brand can make a difference.  What we really need is someone who works with VCP codes and monitors everyday perhaps someone involved in the manufacturing process.  One think to note is some programs like softMCCS send VCP codes and if we could figure out which codes there sending it would be clear as day.  However the output from softMCCS is hard to understand its not something simple as: "You said this so we sent this code with that value, then sent another code with a different value10."


My script runs in A_AhkVersion:=1.1.22.07, get the latest version at http://ahkscript.org/download/

Check out this AutoHotkey tutorial: http://ahkscript.git...o/AHK_Tutorial/

Read the documentation: http://ahkscript.org.../AutoHotkey.htm


BoseRoHS
  • Members
  • 1 posts
  • Last active: Jan 14 2014 01:33 PM
  • Joined: 14 Jan 2014

Would this be something similar to what (http://www.entechtaiwan.com/) mControl does?

 

I'm looking for an alternative to mControl, since I just installed it a day ago and the 21-day evaluation expired and unable to evaluate it further, an uninstall/reinstall does not solve the issue! Can't even register to their support forums since they have registration disabled, lacking support to their products. I believe mControl to be very useful.

 

Unfortuneately, no one out there programs such a tool, I've got two computers utilitizing both inputs on a single monitor and it would be nice to have a simple hotkey, avoiding the physical monitor button, to switch between the inputs. Too combersome, and unproductive, to reach under the monitor to switch between inputs verses a keyboard shortcut on the fly.

 

 

 

Edit:

 

After more digging I found NirCmd and some helpful information from brainwreckedtech, but I'd like to know how this would work on a system that has dual monitors on the host computer and the monitor I want to switch inputs (and control - with microsoft garage) to view the other computer is the second monitor.

 

Normal function with a single monitor is:

nircmd.exe cmdwait 500 monitor off

Though, how would that be written to select the respective monitor 1 or 2?