Finding available shortcut keys (originally "Where's the 'New Window' command?")
-
I never want to become that horrible programmer who blindly copies from other programs without taking the time to understand what the code is doing.
Very commendable!
… is much easier for me to wrap my head around.
This is pretty basic Windows programming stuff, I’d say, but if you’re new to Windows programming, then let me briefly explain how this usually works.
Whenever you want to interact with a GUI application in Windows, you need its ID, the HWND that is the handle of a window. You can get this by using user32.dll functions such as FindWindow and FindWindowEx.
To communicate with the window, use functions like SendMessage.
For example, TCM_GETITEMCOUNT is a message sent to a SysTabControl32 to query the number of available tabs.BGM_GETROWS is defined by Notepad++ itself.
SetForegroundWindow is used to ensure that the following simulated keystrokes (keybd_event) are sent to the application they are intended for.
-
@TBugReporter said in Where’s the “New Window” command?:
I don’t know if it’s differences in programming style, or just the fact that your (Eko) script is doing all the heavy lifting, but @Alan-Kilborn’s is much easier for me to wrap my head around.
This is totally because Eko’s script IS doing the “heavy lifting”. My script is simple in comparison.
When you see
ctypes
in a Python program, expect “heavy lifting”, “magic”, and “pixie dust” to be on display. :-) -
@Alan-Kilborn said in Where’s the “New Window” command?:
When you see ctypes in a Python program, expect “heavy lifting”, “magic”, and “pixie dust” to be on display. :-)
:-D and it works only during full moon and when you dance around a fire :-D
-
I’m dancing as fast as I can (meaning “as my spare time allows”), but I’ve hit a snag. I want my script’s output to read the name of the tab where a given shortcut was found, but the descriptions I’ve found of how to do this for other languages either assume the existence of library functions in that language which I can’t find source code to, or else they dive headfirst into deep voodoo without a life jacket. :-}
I’m guessing I have to do something like
user32.SendMessageW(sys_tab_hwnd, TCM_GETITEMCOUNT, 0, 0)
but send a different message, and figure out how to read the response. Any chance one of you could point me in a less random direction?
Also, given that this thread has drifted so far away from the original topic, is there any way I can change its title?
-
I can take a look today after work (in 6-7 hours).
-
Hello, @tbugreporter ,
Regarding specifically the title changes, which title would you like to see ? As a moderator, I can modify it easily !
BR
guy038
-
Found the time to try it out during my lunch break.
TCM_GETITEMW = (TCM_FIRST + 60) # get the current tab message TCIF_TEXT = 1 # flag to specify that we are only interested in pszText # define the storage that will contain the requested information. class TCITEM(ctypes.Structure): _fields_ = [('mask', wintypes.UINT), ('dwState', wintypes.DWORD), ('dwStateMask', wintypes.DWORD), ('pszText', wintypes.LPWSTR), ('cchTextMax', wintypes.INT), ('iImage', wintypes.INT), ('lParam', wintypes.LPARAM)] pszText = ctypes.create_unicode_buffer(260) # create a buffer to hold the tab text tcitem = TCITEM() # create an instance tcitem.mask = TCIF_TEXT # specify that we want to read the pszText field tcitem.pszText = addressof(pszText) # points to the tab text buffer tcitem.cchTextMax = len(pszText) # length of buffer pITEM = byref(tcitem) # pointer to the concrete struct TCITEM # within the for loop call found = user32.SendMessageW(sys_tab_hwnd, TCM_GETITEMW, tab, pITEM) if found: print(tcitem.pszText)
Seems to work, let me know if anything is unclear.
-
which title would you like to see ?
How about
Finding available shortcut keys (originally "Where's the 'New Window' command?")
As a moderator, I can modify it easily !
TYVM!
Seems to work, let me know if anything is unclear.
Yes, that looks like the info I needed; now I just have to add it to the script.
TYVM to you too!
-
-
NameError: global name 'byref' is not defined
Try ctypes.byref instead.
-
Here’s a question from the “newless cluebie to Python” department:
I’m currently struggling with errors like
NameError: global name 'my_new_variable' is not defined
I read that there’s a “global” statement that can help, but it doesn’t seem to work for me. Exactly where should this go? Or, is there another way I can rearrange the code that will avoid this?
-
In the function in which it is used, suppose there is a code like this
x = 42 y = {'x': 42} def main(): global x x += 1 y['x'] += 1 print(x) print(y) main()
x
needs to be defined as global, while it is not necessary fory
, because it is a dict. -
The pest is back! 😁 (I thank you in advance for your patience with me.)
-
Can I use PythonScript to display a Windows MessageBox? Can I create my own custom dialogs in Windows style?
-
How can I prematurely end my script (if something weird happens)? I found
sys.exit()
, but this apparently terminates all of Notepad++ along with the script.
-
-
@TBugReporter said in Finding available shortcut keys (originally “Where’s the ‘New Window’ command?”):
- Can I use PythonScript to display a Windows MessageBox?
Yes. 😉1
Can I create my own custom dialogs in Windows style?
Not easily. 😉2
- How can I prematurely end my script (if something weird happens)? I found
sys.exit()
, but this apparently terminates all of Notepad++ along with the script.
The best way I’ve found is to have a bunch of “if” processing so that it keeps on dumping out without running any of your code
----
WinkNotes: 😉3
😉1:
notepad.messageBox()
😉2: Alan tends to get around this by doing a bunch of free-form
editor.input()
notepad.prompt()
calls, and then processing the text that the user types in to make the decisions. In theory, since PythonScript comes with the libraries necessary to access any of the win32 API functions: see plenty of examples in the forum with accessing SendMessage; searching the forum on theSendMessage
from win32 API, and narrowing it down to @Ekopalypse’s posts, will get you some good examples pretty quickly – you would then have to extrapolate from that on how to access the various win32 API functions you want. But that said, I don’t know how practical it is to build a whole window using raw API calls – normally when programming win32 API, you would use resource files or equivalents, but I have no clue if you can define a resource file and easily give access to that resource file to the Python interpreter in PythonScript. (If you figure out a way, let me know, because I want to use that to reduce my library requirements in PerlScript some day.)😉3: wink notes are similar to footnotes, but made more annoying because I hid my actual answer inside the footnotes rather than in the main flow of the conversation
-
@PeterJones said in Finding available shortcut keys (originally “Where’s the ‘New Window’ command?”):
The best way I’ve found is to have a bunch of “if” processing
If I have to resort to something like that, I’d use
while True: pass
instead. (Still an evil hack, but it seems slightly more elegant.)
-
With ctypes you have access to the Windows Api and can therefore do everything it offers. E.g. create a TaskDialog.
You can also build your own dialogs with the included Tkinter module, see for example the Formatter.py script from the demo directory.
As for sys.exit, I found out that calling a “main” function and returning from that function serve the same purpose.
def main(): if x != 0: return main()
-
@PeterJones said in Finding available shortcut keys (originally “Where’s the ‘New Window’ command?”):
free-form
editor.input()
callsIt was pointed out to me that it should have said
notepad.prompt()
. sorry for the confusion. I have updated the original post to not confuse future readers. -
@Ekopalypse said in Finding available shortcut keys (originally “Where’s the ‘New Window’ command?”):
You can also build your own dialogs with the included Tkinter module
For me, this approach is just “too much” as in “complication” but to each his own. Maybe I’ve just never liked Tkinter in general.
I don’t know, I’ve felt that the “mini UIs” I’ve been able to create with the
notepad.prompt()
window are lightweight and workable… A classic example would be in this THREAD; see the script in theDec 16, 2017, 11:03 PM
posting. -
Was your screenshot created with the Tkinter library, or with raw calls to the TaskDialog? If with raw calls, could you share the code (as a gist if it’s too long to fit nicely in the forum)?
-
I don’t use Tkinter either, but as you said it is an alternative.
90% of my scripts I use have a configuration section, so no dialog at all. The rest use dialogs like the task dialog.
Just my preference - could be done differently.The screenshot with the TaskDialog was created with ctypes and the corresponding Win32 API calls.
Give me a few minutes to create a standalone, callable version. I’ll post the link to the gist once I’m done.