I completed several tests with most System-Defined messages and I have now more precise details about this matter. The bad news first: these messages can be send to
existing windows components only, that is, a menu bar, scroll bar, selection boxes, etc. There is no way to
create a new window component in order to make good use of the rest of messages, like creating an animation control to display an .AVI file via the
ACM messages. However, there are still some messages not covered in the first post of this thread that can be used in the cmd.exe Window or in other applications.
One of the simplest ones is
WM_CHAR=0x0102=258 message (previously suggested by user mcnd) that allows to inject a key in the keyboard input buffer this way:
SendMessage %WM_CHAR% AsciiCode. Although this message is
similar to other keyboard input methods (like JScript's SendKeys) there are subtle differences, so I need to complete more tests in order to get precise details on this message (and also on
WM_SYSCHAR similar one).
Another useful message is
WM_COMMAND=0x0111=273, that selects an item from the topmost menu of an application. All windows have a
Window menu (formerly known as
System menu, name that I prefer) represented by the title bar, that include the SC_MINIMIZE, SC_MAXIMIZE and SC_CLOSE item ID's at least. Most windows also include a
Topmost menu, that is the standard application menu (an exception is cmd.exe, that groups its few edition options in the system menu). This means that each menu item must be selected with the right message: WM_SYSCOMMAND for System menu items and WM_COMMAND for Topmost menu items. This point return us to the same problem stated in the first post of this thread: know the values that allow us to access useful features in application programs.
In order to solve this point, I wrote a program called InspectMenu.exe that inspect the system and topmost menus of an active application and list the values of their item ID's and the short description that appears in the corresponding pop-up menu. When I ran this program in the cmd.exe window I got a series of additional values for the system menu:
Code: Select all
C:\Users\Antonio\Documents\ASMB> InspectMenu.exe
System menu:
0 - F120: &Restaurar
1 - F010: &Mover
2 - F000: &Tama±o
3 - F020: Mi&nimizar
4 - F030: Ma&ximizar
5 - 0000:
6 - F060: &Cerrar
7 - ---> &Editar
0 - FFF2: M&arcar
1 - FFF0: C&opiar Entrar
2 - FFF1: &Pegar
3 - FFF5: &Seleccionar todo
4 - FFF3: &Desplazar
5 - FFF4: &Buscar...
8 - FFF8: Pre&determinados
9 - FFF7: &Propiedades
Topmost menu:
No menu
This point confirms that the SC_SCROLL=0xFFF3=65523 value, described in the first post of this thread, is
not a standard item used to enable the scroll mode in any application, but a particular value used just by cmd.exe, so there is no reason to document it as user kero indicated. This means that "SC_SCROLL" is an incorrect name because it is not a general value, like the other standard names that starts with "SC_", so I now choose the "CMD_" prefix for the particular values used in cmd.exe application.
Code: Select all
rem Values for ItemID's in the System (Window) menu of cmd.exe:
set /A CMD_Mark=0xFFF2, CMD_Copy=0xFFF0, CMD_Paste=0xFFF1, CMD_SelectAll=0xFFF5, CMD_Scroll=0xFFF3, CMD_Find=0xFFF4
set /A CMD_Defaults=0xFFF8, CMD_Properties=0xFFF7
InspectMenu.exe may also show the menu items of other applications; just give the window title between quotes in the parameter. For example, to get the menu items of Windows Calculator accessory I used
InspectMenu.exe "Calculadora" (in Spanish) that show a three-level topmost menu with 21 total final item ID's. Below there are some of these values (with "CAL_" prefix) and the most useful item ID's of Windows Notepad text editor (with "NP_" prefix).
Code: Select all
rem Values for ItemID's in the topmost menu of calc.exe (Windows Calculator):
set /A CAL_Copy=0x012C, CAL_Paste=0x012D, CAL_GroupDigits=0x012F
rem Values for ItemID's in the topmost menu of Windows Notepad.exe:
set /A NP_New=0x0001, NP_Open=0x0002, NP_Save=0x0003, NP_SaveAs=0x0004, NP_Quit=0x0007
set /A NP_Cut=0x0300, NP_Copy=0x0301, NP_Paste=0x0302, NP_Delete=0x0303
set /A NP_Find=0x0015, NP_FindNext=0x0016, NP_Replace=0x0017, NP_SelectAll=0x0019
When I was writting this text (in Notepad), I execute InspectMenu and then copy the output from the screen via the rudimentary right-click mouse method in order to paste it into the Notepad document. After just two times of do that I tired of the cumbersome procedure, so I opted to write the following
PasteInto.bat Batch file:
Code: Select all
@echo off
setlocal
rem PasteInto.bat: Take the screen contents of the current cmd.exe window
rem and paste it into another Notepad active window
rem Antonio Perez Ayala
if "%~1" neq "" goto begin
echo Copy-paste the contents of the cmd.exe screen into a Notepad window
echo/
echo PasteInto "Title of Notepad recipient window"
goto :EOF
:begin
rem Define auxiliary values
call SendMessageValues.bat
rem Select all text in this window and copy it to clipboard
SendMessage %WM_SYSCOMMAND% %CMD_SelectAll%
SendMessage %WM_SYSCOMMAND% %CMD_Copy%
rem Activate the other window via Minimize/Restore trick
SendMessage "%~1" %WM_SYSCOMMAND% %SC_MINIMIZE%
SendMessage "%~1" %WM_SYSCOMMAND% %SC_RESTORE%
rem Paste clipboard contents into the other window
SendMessage "%~1" %WM_COMMAND% %NP_Paste%
The development of this program presented a problem: the items in the Notepad topmost menu can
not be selected if the window was not active. I did some tests and discovered that this point depends on the relation that the cmd.exe window have (has?) with the other window and the particular program in the other window. For example, in the case of Calculator Windows accessory, its menu items can be selected when the window is not active, and even when the window is minimized! I tried to develop a method to activate other window from the cmd.exe one using just System-Defined messages. I did several tests using diverse combinations of
WM_ACTIVATE,
WM_CANCELMODE,
WM_ENABLE,
WM_ACTIVATEAPP,
WM_SETFOCUS and
WM_KILLFOCUS messages, with no success. Fortunately, the items
in the system menu of any window can be selected from another window, and after a SC_RESTORE the restored window remains active; this behavior makes possible to activate Notepad and other windows from the cmd.exe one via a Minimize/Restore procedure.
The mechanism used in this Batch file allow us to use other Windows applications as "servers" for a "client" Batch file in the way described in
Dynamic Data Exchange, although in a rudimentary way. The following Batch file is an example of this technique that use the Calculator Windows accessory to perform arithmetic operations.
Code: Select all
@echo off
setlocal
rem UseCalc.bat: Example of using Windows Calculator accessory as "server" for a "client" Batch file
rem Antonio Perez Ayala
rem Define auxiliary variables
call SendMessageValues.bat
set "1/x=R" & set "Inv=I" & set "Mod=D" & set "Log=L" & set "Int=;" & set "Sqrt=@"
set "Sin=S" & set "Cos=O" & set "Tan=T" & set "DMS=M" & set "F-E=V" & set "Pi=P"
set "Exp=X" & set "x^2=Q" & set "x^y=Y" & set "x^3=#" & set "Ln=N"
rem Start the "server" and minimize it
start calc
ping -n 2 localhost > NUL
SendMessage "Calculator" %WM_SYSCOMMAND% %SC_MINIMIZE%
rem Define a list of arithmetic expressions as examples
set "X=1.5"
for %%n in (^"^
% Do NOT remove this line %
^") do for /F "tokens=1,2" %%a in ("
"e 1%Inv%%Ln%" %%~n
"Pi %Pi%" %%~n
"Ln(10) 10%Ln%" %%~n
"Sqrt(2) 2%Sqrt%" %%~n
"TanH(%X%) (%X%%Inv%%Ln%-(0-%X%)%Inv%%Ln%)/(%X%%Inv%%Ln%+(0-%X%)%Inv%%Ln%)" %%~n
"(4+5)/(6+7) (4+5)/(6+7)" %%~n
"(((4+5)*(2+3)+6)/(8+7))^9 (((4+5)*(2+3)+6)/(8+7))%x^y%9" "
) do (
rem Copy the Calculator expression into clipboard
< NUL (set /P "=%%~b="| clip)
rem Paste the expression to Calculator
SendMessage "Calculator" %WM_COMMAND% %CAL_Paste%
rem Copy the result into clipboard
SendMessage "Calculator" %WM_COMMAND% %CAL_Copy%
rem Read the result from clipboard (paste clipboard)
for /F %%c in ('PasteClip') do echo %%~a = %%c
)
rem Change number format to show a last result
SendMessage "Calculator" %WM_COMMAND% %CAL_GroupDigits%
echo 2%x^y%64=| clip
SendMessage "Calculator" %WM_COMMAND% %CAL_Paste%
SendMessage "Calculator" %WM_COMMAND% %CAL_Copy%
SendMessage "Calculator" %WM_COMMAND% %CAL_GroupDigits%
echo/
for /F %%c in ('PasteClip') do echo 2^^64 = %%c
rem Close the "server"
SendMessage "Calculator" %WM_SYSCOMMAND% %SC_CLOSE%
Output:
Code: Select all
e = 2.7182818284590452353602874713527
Pi = 3.1415926535897932384626433832795
Ln(10) = 2.3025850929940456840179914546844
Sqrt(2) = 1.4142135623730950488016887242097
TanH(1.5) = 0.9051482536448664382423036964565
(4+5)/(6+7) = 0.69230769230769230769230769230769
(((4+5)*(2+3)+6)/(8+7))^9 = 60716.992766464
2^64 = 18,446,744,073,709,551,616
You should note that the names of all Windows accessories are language dependant. I copied the keys used to assemble the arithmetic expression for Calculator from a list of
Keyboard shortcuts; the next step is test if WM_CHAR/WM_SYSCHAR message could be used to generate the rest of Alt- and Ctrl- Calculator keys. Although this Batch file is somewhat slow (because all those copy to/from clipboard commands), the interesting point is that it works!
The next step is write a Batch file that use Notepad as server to replace strings in a text file. If I have success, I think that it would be possible to edit an Excell spreadsheet or access any other Window application in the same way!
Technicall note. The cmd.exe system menu include the CMD_Paste item ID that effectively paste the clipboard contents
into cmd.exe keyboard input buffer; this means that such input could be get via a SET /P command or any other method that read input via Stdin. For example, the "Read the result from clipboard" part in previous Batch file could be written this way:
Code: Select all
rem Read the result from clipboard via SET /P
SendMessage %WM_SYSCOMMAND% %CMD_Paste% & rem Paste clipboard contents
SendMessage %WM_CHAR% %EnterKey% & rem Add an Enter to complete SET /P input
set /P "result=" & rem Read a line from clipboard in result variable
You may also use a FOR that run a filter command to get such input, like FIND or FINDSTR, or you may use a COPY CON FILE.TXT command to copy all lines from clipboard to a file, but in these cases it would be necessary to insert a Ctrl-Z before the Enter in order to mark the end of input for these commands. For example:
Code: Select all
rem Copy-Paste clipboard contents into Clipboard.txt file
SendMessage %WM_SYSCOMMAND% %CMD_Paste% & rem Paste clipboard contents
SendMessage %WM_CHAR% %Ctrl_Z% & rem Mark the End-Of-File for COPY command
SendMessage %WM_CHAR% %EnterKey% & rem Add an Enter to complete the input
copy con Clipboard.txt & rem Do it!
These methods works correctly, but have a disadvantage: they all
show in the screen the characters being pasted! This is logical because supposedly these characters are being typed in the keyboard, but they interfere with any program that require such paste operations. I tried to develop a method to avoid this text appearing in the screen, with no success. For this reason, I wrote PasteClip.exe program that performs the complementary function of native CLIP.EXE command: it read the clipboard contents and show it via its Stdout channel, so this output can be processed in the usual way with no problems.
- SendMessage 2nd part.zip
- InspectMenu.exe, PasteClip.exe, PasteClip.txt, PasteInto.bat and UseCalc.bat; and updated version of SendMessageValues.bat
- (4.75 KiB) Downloaded 780 times
Antonio