Home Download Buy Blog Forum Support

[Solved] Problem inside Plugin (ApplicationCommand)

[Solved] Problem inside Plugin (ApplicationCommand)

Postby BugFix on Thu Jul 31, 2014 7:08 pm

Hi,
I've created a Plugin named "Test". It calls from Win32.api the MessageboxA.
If I execute the api-call with Ctrl+B it works like expected.
But if I bind the call inside a ApplicationCommand class, I get an error.

This code works with Ctrl+B
Code: Select all
from ctypes import *

MB_DEFBUTTON1 = 0x0
MB_DEFBUTTON2 = 0x100
MB_DEFBUTTON3 = 0x200
MB_ICONASTERISK = 0x40
MB_ICONEXCLAMATION = 0x30
MB_ICONHAND = 0x10
MB_ICONINFORMATION = MB_ICONASTERISK
MB_ICONQUESTION = 0x20
MB_ICONSTOP = MB_ICONHAND
MB_OK = 0x0
MB_OKCANCEL = 0x1
MB_YESNO = 0x4
MB_YESNOCANCEL = 0x3
MB_ABORTRETRYIGNORE = 0x2
MB_RETRYCANCEL = 0x5

class MessageBox:
    def box_a(self, text, title='Message Box', utype=MB_OK, hwnd=None):
        mb = windll.user32.MessageBoxA
        mb(hwnd, c_char_p(text), c_char_p(title), c_long(utype))

msg = MessageBox()
msg.box_a('Thats a message')


And this code was created as plugin "test" and bind with "F12".
Code: Select all
import sublime, sublime_plugin
from ctypes import *

MB_DEFBUTTON1 = 0x0
MB_DEFBUTTON2 = 0x100
MB_DEFBUTTON3 = 0x200
MB_ICONASTERISK = 0x40
MB_ICONEXCLAMATION = 0x30
MB_ICONHAND = 0x10
MB_ICONINFORMATION = MB_ICONASTERISK
MB_ICONQUESTION = 0x20
MB_ICONSTOP = MB_ICONHAND
MB_OK = 0x0
MB_OKCANCEL = 0x1
MB_YESNO = 0x4
MB_YESNOCANCEL = 0x3
MB_ABORTRETRYIGNORE = 0x2
MB_RETRYCANCEL = 0x5

class TestCommand(sublime_plugin.ApplicationCommand):
    def run(self):
        self.box_a('Test-Box')

    def box_a(self, text, title='Message Box', utype=MB_OK, hwnd=None):
        mb = windll.user32.MessageBoxA
        mb(hwnd, c_char_p(text), c_char_p(title), c_long(utype))

This fails with error message:
mb(hwnd, c_char_p(text), c_char_p(title), c_long(utype))
TypeError: bytes or integer address expected instead of str instance

What do I wrong?

Thanks in advance.
Last edited by BugFix on Thu Jul 31, 2014 11:50 pm, edited 1 time in total.
BugFix
 
Posts: 7
Joined: Fri May 17, 2013 9:29 am

Re: Problem inside Plugin (ApplicationCommand)

Postby sapphirehamster on Thu Jul 31, 2014 10:18 pm

I'm guessing you are using Python 2 when you run the build command. Sublime uses Python 3 which handles strings and bytes significantly differently.

First off, a little tip, you don't always have to explicitly cast values with ctypes. It will often figure out the type for you.

MessageBoxA is the ANSI version. If you want to use that, you have to first convert Python's unicode strings into something it can handle, like this:

Code: Select all
import locale
preferred_encoding = locale.getpreferredencoding(False)
mb(hwnd, text.encode(preferred_encoding), title.encode(preferred_encoding), utype)


However, that's a pain. It's better to just use the "wide" Unicode version:

Code: Select all
mbw = windll.user32.MessageBoxW
mbw(hwnd, text, title, utype)


Also, you may find that your dialog box will pop up in the background. This is because the plugin runs in a background process separate from sublime. The handle to the window will be None. AFAICT, you can access the hwnd from sublime's window object, but that will hang sublime. You can try adding MB_TOPMOST or MB_SYSTEMMODAL flag to the utype options.

Personally I do not like popup windows. I'm not sure what you are trying to achieve, but I encourage you to look at other options.
sapphirehamster
 
Posts: 88
Joined: Sun Jul 01, 2012 11:19 pm

Re: Problem inside Plugin (ApplicationCommand)

Postby BugFix on Thu Jul 31, 2014 11:47 pm

Thanks for your explanation.
That I've used a message box was only a test for me, to handle sublime_plugin.ApplicationCommand.
I've written some plugins for SciTE editor (in Lua). And now I want to do the same for ST. It's a very fine editor and so I'm learning Python too. ;)
BugFix
 
Posts: 7
Joined: Fri May 17, 2013 9:29 am


Return to Plugin Development

Who is online

Users browsing this forum: Yahoo [Bot] and 8 guests