Перейти к содержанию
Fire Monkey от А до Я

dnekrasov

Пользователи
  • Постов

    317
  • Зарегистрирован

  • Посещение

  • Победитель дней

    52

Сообщения, опубликованные dnekrasov

  1. Попробуйте ещё так сделать:

      if not FSet and (Msg.WParam = IMN_SETCANDIDATEPOS) then
      begin
        FSet := True;
        Imc:=ImmGetContext(FMXHandleToHWND(Handle));
    //    ImmGetCandidateWindow(Imc,0,@ImeCandidateFormProperties);
        ImeCandidateFormProperties.dwIndex:=0;
        ImeCandidateFormProperties.dwStyle:=CFS_CANDIDATEPOS;
        ImeCandidateFormProperties.ptCurrentPos.X:=100;
        ImeCandidateFormProperties.ptCurrentPos.Y:=100;
        ImeCandidateFormProperties.rcArea:=Rect(0,0,100,100);
        Msg.Result := LResult(ImmSetCandidateWindow(Imc,@ImeCandidateFormProperties));
        ImmReleaseContext(FMXHandleToHWND(Handle),Imc);
        FSet := False;
      end;

    где FSet это глобальное поле типа Boolean. Намного меньше раз заходит в процедуру и более правильно отрабатывает - нет рекурсии вызова.

  2. 56 минут назад, Вадим Смоленский сказал:

    Что еще тут стоит проверить?

    Сложно что-то посоветовать, когда не можешь повторить ошибку... Попробуйте задать ImeCandidateFormProperties.dwIndex  и ImeCandidateFormProperties.rcArea. Зачем вообще вызывать ImmGetCandidateWindow(Imc,0,@ImeCandidateFormProperties)? Попробуйте поиграться со значением ImeCandidateFormProperties.dwStyle 

  3. 1 час назад, Вадим Смоленский сказал:

    трудно надеяться, что вы сможете помочь - но вдруг?

    Попробовал... Не понял что такое LookUp.Handle - заменил на просто Handle и вызываю только если Msg.WParam = IMN_SETCANDIDATEPOS. Всё работает без ошибок. Вот мой код

    procedure TMainForm.WMIMENotify(var Msg: TMessage);
    var
      Imc: HIMC;
      ImeCandidateFormProperties: TCandidateForm;
    begin
      if Msg.WParam = IMN_SETCANDIDATEPOS then
      begin
        Imc:=ImmGetContext(FMXHandleToHWND(Handle));
        ImmGetCandidateWindow(Imc,0,@ImeCandidateFormProperties);
        ImeCandidateFormProperties.dwStyle:=CFS_CANDIDATEPOS;
        ImeCandidateFormProperties.ptCurrentPos.X := 100;
        ImeCandidateFormProperties.ptCurrentPos.Y := 100;
        ImmSetCandidateWindow(Imc,@ImeCandidateFormProperties);
        ImmReleaseContext(FMXHandleToHWND(Handle),Imc);
      end;
    end;

     

  4. 37 минут назад, Вадим Смоленский сказал:

    Во время запуска приложения управление множество раз переходит в NewWndProc

    Ну это нормально - теперь все сообщения окну обрабатываются в NewWndProc

    37 минут назад, Вадим Смоленский сказал:

    Но как только главное окно появилось на экране - больше ни разу, ни с какими сообщениями вообще

    А вот это странно - я этот механизм использую еще начиная с XE4 и везде отрабатывал без проблем. Единственное, что мог бы посоветовать - попробуйте перенести переопределение WndProc в CreateHandle.

    WinHook.zip

    UPD

    Поднял старые проекты - именно в CreateHandle я это и делал. 

  5. Делаем как обычно, если надо переопределить какое-то событие окна

    interface
    
    uses
      {$IFDEF MSWINDOWS}
      Winapi.Windows, Winapi.Messages,
      FMX.Platform.Win,
      {$ENDIF}
    
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs;
    
    type
      TMainForm = class(TForm)
      private
        procedure CreateHandle; override;
    
        {$IFDEF MSWINDOWS}
        procedure WMIMENotify(var Msg: TMessage); message WM_IME_NOTIFY;
        {$ENDIF}
      public
      end;
    
    var
      MainForm: TMainForm;
    
    implementation
    
    {$R *.fmx}
    
    {$IFDEF MSWINDOWS}
    var
      OldWndProc: Pointer = nil;
    
    function NewWndProc(Wnd: HWND; Msg: UINT; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
    var
      Mess : TMessage;
    begin
        case Msg of
          WM_IME_NOTIFY:
          begin
            Mess.Msg := Msg;
            Mess.WParam := wParam;
            Mess.lParam := lParam;
            Mess.Result := 0;
            MainForm.Dispatch(Mess);
            Result := Mess.Result;
          end;
          else
            Result := CallWindowProc(OldWndProc, Wnd, Msg, WParam, LParam);
        end;
    end;
    
    {$ENDIF}
    
    { TMainForm }
    
    procedure TMainForm.CreateHandle;
    begin
      inherited CreateHandle;
    
      {$IFDEF MSWINDOWS}
      OldWndProc:= Pointer(SetWindowLong(WindowHandleToPlatform(Handle).Wnd, GWL_WNDPROC, Integer(@NewWndProc)));
      {$ENDIF}
    end;
    
    {$IFDEF MSWINDOWS}
    procedure TMainForm.WMIMENotify(var Msg: TMessage);
    begin
      {что-то делаем}
    end;
    {$ENDIF}

     

  6. 4 часа назад, Алиса Романец сказал:

    Везде написано, что, мол, "замена курсора в FMX не работает"

    Ещё как работает, во всяком случае под винду. Но именно курсора (cur) а не изображения (bmp).

    CustomCursor.zip

  7. 1 минуту назад, Barbanel сказал:

    В десятке тоже нужно перелогиниться?
    Помню только про семерку.

    Да. После изменения масштаба отображаться начинает вроде нормально, даже без перезагрузки приложения, а вот многие API-шные функции, относящиеся к работе с масштабом возвращают старые значения.

  8. 1 минуту назад, POV сказал:

    Если нужно будет перелогиниваться, то это несерьезно.

    Да нет. Это вполне серьёзно. Это настройка и особенность винды и Delphi тут ни при чём. Так что для отладки используйте способ, описанный мною чуть выше. Без перелогина после изменения масштаба Вы ничего не увидите. Заранее сочувствую - я помню как сам намучался, когда отлаживал подобное.

  9. В 28.10.2018 в 04:46, POV сказал:

    В доступе планшета нет, как отлаживать не придумаю

    Для отладки - заведите в винде нового пользователя, у него установите масштаб побольше и, переключаясь между основным и ним, отлаживайтесь. Немного геморно но... за неимением гербовой... и т.д. по тексту :)

  10. 4 минуты назад, POV сказал:

    Оно какое-то нерабочее. Тут я находил такие советы - масштаб читается как 1, хотя я задал 125%.

    Система? Версия Delphi? У меня проблемы возникают только если подключено 2 монитора и на одном мониторе 125, а на другом 100. Кстати - после изменения масштаба обязательно перелогиниться, иначе не всё подхватывается.

  11. 34 минуты назад, Barbanel сказал:

    Попробуйте учитывать Screen.PixelsPerInch

    Это олдскул. Есть FMX.Platform.IFMXScreenService.GetScreenScale, FMX.Helpers.Win.GetDCScale и FMX.Helpers.Win.GetWndScale

  12. Если правильно помню - у меня проблема была в том, что при расчете использовал как размеры и положение контролов на форме, так и самой формы (как и у Вас). Где-то они уже преобразованы в соответствии с масштабом, а где-то - нет. Для начала попробуйте вычислять координаты с помощью функций ScreenToClient и ClientToScreen, не используя Left, Top, Width и Height формы

    Я не знаю - баг это был или нет (если баг - то может уже исправлен), но в конечном итоге, умножая то одно то другое на Scale винды, я добился нормального отображения. 

    Замечу, что многое зависит от системы, на которой запускалось приложение - разное поведение на Win7, Win8, Win8.1 и Win10. Так же проверьте - выставлен ли параметр Enable High DPI в параметрах проекта - в зависимости от него API-шные функции винды возвращают разные значения.

  13. 6 часов назад, POV сказал:

    Исходя из габаритов разных там компонентов и другой формы, рассчитываю Top и Left интересующей меня формы

    Покажите код. У меня когда-то была похожая проблема - может чё посоветую.

  14. 1 час назад, sulion сказал:

     * сдвиг картинки в bitmap

     * совмещение нескольких (например, двух) битмапов на одном

    И, пожалуй, всё - остальное могу :)

    drawbitmap.7z

    Чёт я совсем не понял что Вы делаете в Вашем примере. Зачем использовать маски при сдвиге и совмещении. Просто берёте нужный кусок битмапки (srcRect) и рисуете его там где Вам нужно (dstRect). Если размеры srcRect и dstRect не будут совпадать, то будет еще и масштабирование.

×
×
  • Создать...