automatische cursoränderung schlägt fehl



  • hallo leute

    hab mir ein ganz einfaches miniframework fuer fensterbasteleien geschrieben.
    nun hab ich damit folgenden effekt: wenn ich ein leeres fenster erstelle und es in der groesse aendere und wieder ins fenster mit dem cursor zurueckfahre, dann aendert sich zeitweise der cursor nicht mehr zum std-pfeil zurueck. dann bleibt der doppelpfeil solange bis ich wieder aus dem fenster rausfahre. dabei muss ich nicht mal unbedingt die groesse aendern. es reicht schon wenn sich der pfeil in den doppelpfeil aendert und ich wieder ins fenster reinfahre. wodurch kann der effekt zustande kommen ?

    ich poste mal die window procs:

    /* (1) */
    LRESULT CALLBACK object::WindowProc(handle_type hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
       CREATESTRUCT *cs = reinterpret_cast<CREATESTRUCT*>(lparam);
    
       if((msg == WM_NCCREATE || msg == WM_CREATE) && static_cast<object*>(cs->lpCreateParams) != nullptr)
       {
          txl::gfx::window_attribute::userdata<object*>(hwnd, static_cast<object*>(cs->lpCreateParams));
          static_cast<object*>(cs->lpCreateParams)->m_handle = hwnd;
          txl::gfx::window_attribute::window_proc(hwnd, object::WindowProcEx);
          return WindowProcEx(hwnd, msg, wparam, lparam);
       }
       else
          return ::DefWindowProcW(hwnd, msg, wparam, lparam);
    }
    
    /* (2) */
    LRESULT CALLBACK object::WindowProcEx(handle_type hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
       object *it = txl::gfx::window_attribute::userdata<object*>(hwnd);
    
       if(it != nullptr && it->m_handle != nullptr)
          return it->window_proc(message(hwnd, msg, wparam , lparam));
       else
          return ::DefWindowProcW(hwnd, msg, wparam, lparam);
    }
    
    /* (3) object-klasse: basisklasse fuer alle fenster */
    LRESULT object::window_proc(const message &msg)
    {
       switch(msg.msg)
       {
          case WM_NCCREATE:
               return on_nccreate(msg, reinterpret_cast<CREATESTRUCT*>(msg.lparam));
    
          case WM_CREATE:
               return on_create(msg, reinterpret_cast<CREATESTRUCT*>(msg.lparam));
    
          case WM_NCCALCSIZE:
               return on_nccalcsize(msg);
    
          case WM_NCDESTROY:
               return on_ncdestroy(msg);
    
          case WM_NCACTIVATE:
               return on_ncactivate(msg, static_cast<BOOL>(msg.wparam) == TRUE);
    
          case WM_CLOSE:
               return on_close(msg);
    
          case WM_DESTROY:
               return on_destroy(msg);
    
          case WM_ENABLE:
               return on_enable(msg, static_cast<BOOL>(msg.wparam) == TRUE);
    
          case WM_QUIT:
               return on_quit(msg, static_cast<int>(msg.wparam));
    
          case WM_SIZE:
               return on_size(msg, static_cast<int>(msg.wparam), LOWORD(msg.lparam), HIWORD(msg.lparam));
    
          case WM_MOVE:
               return on_move(msg, LOWORD(msg.lparam), HIWORD(msg.lparam));
    
          case WM_NULL:
               return on_null(msg);
    
          case WM_GETMINMAXINFO:
               return on_getminmaxinfo(msg, reinterpret_cast<::MINMAXINFO*>(msg.lparam));
    
          default:
              return default_handler(msg);
       }
    }
    
    /* (4) meine konkrete fensterklasse, die ich zum testen erstellt habe */
    LRESULT JobItems::window_proc(const txl::gfx::message &msg)
    {
       switch(msg.msg)
       {
          case WM_COMMAND:
               if(msg.lparam == 0 && msg.wparam == 50000)
               {
                  ::PostQuitMessage(2);
                  return 0;
               }
               break;
    
          default: break;
       }
       return base_window::window_proc(msg);
    }
    
    /* DefWindowProc */
    LRESULT object::default_handler(const message &msg)
    {
       return ::DefWindowProcW(msg.hwnd, msg.msg, msg.wparam, msg.lparam);
    }
    

    die funktion (1) wird nur solange aufgerufen bis WM_NCCREATE oder WM_CREATE angekommen ist. dann wird auf WindowProcEx (2) geaendert.
    WindowProcEx ruft dann immer die virtuelle funktion window_proc auf.

    in allen on_xxx memberfunktionen wird immer nur

    default_handler(msg)
    

    aufgerufen.

    hat jemand eine idee woran das liegen koennte ?

    Meep Meep


  • Mod

    Hast Du denn in allen Deinen Handlern einen Aufruf auf den Defaulthandler drin?
    Das kann man ja nicht sehen!



  • ja ueberall nur der aufruf von default_handler. hatte ich im ersten post reingeschrieben damit ich die handler nicht posten muss. aber ich mach es trotzdem 🙂

    LRESULT object::on_nccreate(const message &msg, const CREATESTRUCT *cs)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_nccalcsize(const message &msg)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_create(const message &msg, const CREATESTRUCT *cs)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_close(const message &msg)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_destroy(const message &msg)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_enable(const message &msg, bool b)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_ncdestroy(const message &msg)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_ncactivate(const message &msg, bool b)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_quit(const message &msg, int ret)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_size(const message &msg, int state, int x, int y)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_move(const message &msg, int x, int y)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_null(const message &msg)
    {
       return default_handler(msg);
    }
    
    LRESULT object::on_getminmaxinfo(const message &msg, ::MINMAXINFO *info)
    {
       return default_handler(msg);
    }
    

    2 handler hab ich in der konkreten klasse ueberschrieben (+ der window_proc):

    LRESULT JobItems::on_destroy(const txl::gfx::message &msg)
    {
       ::PostQuitMessage(1);
       return 0;
    }
    
    LRESULT JobItems::on_create(const txl::gfx::message &msg, const CREATESTRUCT *cs)
    {
       HMENU menubar = ::CreateMenu();
       HMENU datei = ::CreateMenu();
    
       ::AppendMenu(menubar, MF_POPUP, (UINT_PTR)datei, TEXT("Datei"));
       ::AppendMenu(datei, MF_STRING, 50000, TEXT("Exit [Alt-F4]"));
    
       ::SetMenu(msg.hwnd, menubar);
    
       return 0;
    }
    
    LRESULT JobItems::window_proc(const txl::gfx::message &msg)
    {
       switch(msg.msg)
       {
          case WM_COMMAND:
               if(msg.lparam == 0 && msg.wparam == 50000)
               {
                  ::PostQuitMessage(2);
                  return 0;
               }
               break;
    
          default: break;
       }
       return base_window::window_proc(msg);
    }
    

    Meep Meep



  • also ich hab jetzt mal folgende WindowProc eingesetzt. ist eine reine freie funktion:

    LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
       switch(msg)
       {
          case WM_CREATE: return 0;
          default: break;
       }
       return ::DefWindowProc(hwnd, msg, wparam , lparam);
    }
    

    der effekt bleibt der selbe. also hat es schon mal nicht mit der nachrichtenverarbeitung meinerseits zu tun. wo kann da der fehler sonst noch liegen ?

    Meep Meep



  • hola

    hab jetzt nochmal rechner neu gestartet und neues projekt angelegt. folgendes ist in der main.cpp:

    #include <Windows.h>
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
       WNDCLASS wndclass;
       wndclass.cbClsExtra = 0;
       wndclass.cbWndExtra = sizeof(LONG_PTR);
       wndclass.hbrBackground = (HBRUSH) ::GetStockObject(WHITE_BRUSH);
       wndclass.hCursor = ::LoadCursor(hInstance, IDC_ARROW);
       wndclass.hIcon = ::LoadIcon(hInstance, IDI_APPLICATION);
       wndclass.hInstance = hInstance;
       wndclass.lpfnWndProc = WindowProc;
       wndclass.lpszClassName = TEXT("DemoApplication");
       wndclass.lpszMenuName = 0;
       wndclass.style = CS_VREDRAW | CS_HREDRAW;
    
       RegisterClass(&wndclass);
    
       HWND hwnd = ::CreateWindow(TEXT("DemoApplication"), TEXT("Demo"), WS_OVERLAPPEDWINDOW, 0, 0, 500, 300, 0, 0, hInstance, 0);
    
       ShowWindow(hwnd, nCmdShow);
       UpdateWindow(hwnd);
    
       MSG msg;
       BOOL ret;
    
       while((ret = ::GetMessage(&msg, 0, 0, 0)) != 0)
       {
          if(ret == -1)
          {
             break;
          }
    
          ::TranslateMessage(&msg);
          ::DispatchMessage(&msg);
       }
    
       return msg.wParam;
    }
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
       switch(msg)
       {
          case WM_CREATE:
               return 0;
    
          case WM_DESTROY:
               ::PostQuitMessage(2);
               return 0;
    
          default:
               return ::DefWindowProc(hwnd, msg, wparam, lparam);
       }
    }
    

    und wieder das selbe. meistens bleibt der doppelcursor haengen wenn ich seitlich ueber das fenster ziehe. hab auch schon im release getestet. selbe effekt. womit kann das zu tun haben ?

    Meep Meep


  • Mod

    Vielleicht hast Du irgendeine supertolle Maussoftware zusätzlich installiert?



  • Ich kenne das Verhalten auch von Qt. Aber ich hab keine Ahnung, warum das passiert oder woran das liegen könnte. Wir werden das auch nicht untersuchen, wäre viel zu komplex. Wir haben teilweise auch GUIs, die aus einer Mischung von Qt und einer anderen UI Lib aufgebaut sind, gibts teilweise alles mögliche. Aber ich meine, das passiert ab und zu auch mit reinen Qt GUIs.
    Passiert aber sehr selten.



  • nein. keine supertolle maussoftware installiert. den effekt hab ich auch nur in visual c++ projekten



  • hab jetzt mal VS2012 installiert. das selbe



  • hab den letzten test mal hochgeladen. source und kompilat. vielleicht koennte
    jemand von euch mal testen ob bei euch das problem auch besteht. einfach langsam
    von links nach rechts ueber das fenster fahren und schauen wie der cursor sich
    verhaelt. ist ein VS2013 project.
    http://komports.de/HelloWin.zip

    Meep Meep



  • so. hab nun das problem gefunden. lag an

    wndclass.hCursor = ::LoadCursor(hInstance, IDC_ARROW);
       wndclass.hIcon = ::LoadIcon(hInstance, IDI_APPLICATION);
    

    da hab ich den hInstance-wert von der WinMain uebergeben.
    wenn ich anstelle hInstance eine 0 uebergebe, dann ist das cursorproblem weg.

    Meep Meep


Log in to reply