ol.mousewheel mxe64

djlbe's icon

scrollmouse.mxe64
mxe64 39.00 KB

Hi,
I managed to compile an 64-bit externals based on the ol.mousewheel object from Oli Larkin. It works (Max 7 64 bit, Windows 7) but I face an important problem as Max crash when I try to create a second instance... that's annoying, did someone has an idea for that ? (that's my very first externals).

The object need to be started using a 'start' message.

Edit.1 : I also found that, used in a big patch, the 'start' message need to be delayed a bit if loadbang is used.
Edit.2 : And it can also block the scroll inside a patcher windows, it really sucks in fact :D ...help :'(
Here is the source code (also on Pastebin : https://pastebin.com/SqQwG5ST):

/**
    @file
    scrollmouse - send scroll messages to output
 
    @ingroup    examples
*/
#include "ext.h"                            // standard Max include, always required
#include "ext_obex.h"                        // required for new style Max object
#include "jit.common.h"
#include <Windows.h>
////////////////////////// object struct
typedef struct _scrollmouse
{
    t_object                    ob;            // the object itself (must be first)
    void *m_outlet1;
    WNDPROC oldproc;
    HWND hWnd;
    t_symbol *ctxt;
} t_scrollmouse;
///////////////////////// function prototypes
//// standard set
void *scrollmouse_new(t_symbol *s, long argc, t_atom *argv);
void scrollmouse_free(t_scrollmouse *x);
void scrollmouse_assist(t_scrollmouse *x, void *b, long m, long a, char *s);
void scrollmouse_start(t_scrollmouse *x);
LRESULT CALLBACK MyOwnWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam);
//////////////////////// global class pointer variable
void *scrollmouse_class;
void ext_main(void *r)
{
    t_class *c;
    c = class_new("scrollmouse", (method)scrollmouse_new, (method)scrollmouse_free, (long)sizeof(t_scrollmouse),
                  0L /* leave NULL!! */, A_GIMME, 0);
    // Methods
    class_addmethod(c, (method)scrollmouse_assist, "assist", A_CANT, 0);
    class_addmethod(c, (method)scrollmouse_start, "start", 0);
    class_register(CLASS_BOX, c); /* CLASS_NOBOX */
    scrollmouse_class = c;
}
void scrollmouse_assist(t_scrollmouse *x, void *b, long m, long a, char *s)
{
    if (m == ASSIST_INLET) { // inlet
        sprintf(s, "need a start message %ld", a);
    }
    else {    // outlet
        sprintf(s, "scroll move %ld", a);
    }
}
void scrollmouse_free(t_scrollmouse *x)
{
    ;
}
void *scrollmouse_new(t_symbol *s, long argc, t_atom *argv)
{
    t_scrollmouse *x = NULL;
    long i;
    if ((x = (t_scrollmouse *)object_alloc(scrollmouse_class))) {
 
        x->m_outlet1 = intout((t_object *)x);
 
    }
    return (x);
}
void scrollmouse_start(t_scrollmouse *x)
{
    void *window;
    if(x->oldproc == NULL)
    {
        window = jit_object_findregistered(x->ctxt);
        if(window) 
        {
            jit_object_method(window, gensym("get_window_ptr"), &x->hWnd);
        } else {
            x->hWnd = main_get_client(); //if no argument, get the patcher window 
        }
 
        if(SetProp(x->hWnd,"scrollmouse", x)) {
                x->oldproc = (WNDPROC) SetWindowLongPtr(x->hWnd, GWLP_WNDPROC,(LONG)MyOwnWndProc);
        } else {
            post("Couldn't setProp()");
        }    
    }    
}
LRESULT CALLBACK MyOwnWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
    t_scrollmouse *x = (t_scrollmouse*) GetProp(hwnd,"scrollmouse");
    switch (umsg)
    {
        case WM_MOUSEWHEEL:
            //post("a");
            //post("%hd", GET_WHEEL_DELTA_WPARAM(wParam));
            outlet_int(x->m_outlet1, (int) GET_WHEEL_DELTA_WPARAM(wParam));
        return 0; // return, or can also pass to orig proc
    }
    if (x && x->oldproc) return CallWindowProc(x->oldproc, hwnd, umsg, wParam, lParam);
    else return DefMDIChildProc(hwnd, umsg, wParam, lParam);
}
11OLSEN's icon

What do you want to do with the wheel input? You want to monitor it but at the same time it should continue to move the scrollbars of the window?

djlbe's icon

Yes, I use it with a JSui, I will add a 'stop' method and activate it only when the mouse is idle. So my biggest problem for the moment is that I can't instantiate it more than once. That's annoying for example, if that externals is inside a bpatcher. then I need to close the main patch before open it so as avoid a Max crash.