Конференция "WinAPI" » Ctrl+C - запрет ОС на копирование в буфер обмена [D7, WinXP]
 
  • allrussia (21.05.10 05:07) [0]
    перехватываю комбинацию в onkeydown контрола

    мне необходимо чтобы работала моя вставка в clipboard, а не системная

     if (ssCtrl in Shift) and (Key = Ord('C')) then
     begin
         Clipboard.Clear;
         MYPasteToClipBoard;
     end;



    такой код не фурычит

    в OnKeyUP  - работает - но нужно долго держать клавиши и отпускать в определенной последовательности, сначала 'С' затем Ctrl.

    С помощью таймера можно заставить работать но это блин смешно и криворуко.

    Существует ли корректный код для запрета CTRL+C (именно чтобы система не лезла в буфер)?
  • Leonid Troyanovsky © (21.05.10 07:31) [1]

    > allrussia   (21.05.10 05:07)  

    > перехватываю комбинацию в onkeydown контрола

    WM_COPY ?

    --
    Regards, LVT.
  • MKC © (21.05.10 09:34) [2]
    брось на форму edit
    положми в него текст потом
    Edit.Selettall.
    edit.copytoclipbord
    попробуй мож пойдет
  • MKC © (21.05.10 09:40) [3]
    тю ты чота я не о том :)
    если тебе нужно чтоб твои компоненты не реагировали на комбинацию клавишь, то key:=#0 в конце onkeydown
    ну а если не в твоем окне то только хук на систему вешать.
  • Riply © (21.05.10 13:21) [4]
    > [0] allrussia   (21.05.10 05:07)
    > перехватываю комбинацию в onkeydown контрола
    > мне необходимо чтобы работала моя вставка в clipboard, а не системная

    IMHO, достаточно перехватить две ф-ии: SetClipboardData, EmptyClipboard
    Во всяком случае, мне в похожей задачке этого хватило.
  • allrussia (21.05.10 16:25) [5]
    > Leonid Troyanovsky

    > WM_COPY ?


    Вы вопрос поняли? Мне нужно чтобы по нажатию Ctrl+C на любом контроле вистема не копировала содержимое в буфер обмена. (Это примерно то же самое что перехват Ctrl+Alt+Del, просто здесь библиотека не участвует) Как скопировать содержимое я знаю.

    MKC

    если тебе нужно чтоб твои компоненты не реагировали на комбинацию клавишь, то key:=#0 в конце onkeydown


    вы тоже особо не поняли видимо: #0 - Это тип Char, а не Word, во вторых - это все равно не поможет (сама система ОС Windows перехватывает CTRL+С, не делфи)

    Riply

    > IMHO, достаточно перехватить две ф-ии: SetClipboardData,
    >  EmptyClipboard
    > Во всяком случае, мне в похожей задачке этого хватило.


    Прекрасно - подскажите как или привдите рабочий пример

    достаточно будет нажать CTRL+C на TEdit или TMemo  и чтобы буфер обмена оказался пустым или с предыдущими данными
  • Riply © (21.05.10 16:42) [6]
    >  [5] allrussia   (21.05.10 16:25)
    > Riply
    > Прекрасно - подскажите как или привдите рабочий пример

    "Подсказать как" что ?
    Как перехватывать API ?
    Если да, то это хорошо расписано у Рихтера и даже с примерами :),
    а если нет, то что именно подсказать ?

    > достаточно будет нажать CTRL+C на TEdit или TMemo  
    > и чтобы буфер обмена оказался пустым или с предыдущими данными

    Эмн... а к чему эта фраза, да еще и выделенная ?
    Разве данные операции работают не через SetClipboardData, EmptyClipboard ?
  • han_malign (21.05.10 16:58) [7]

    > onkeydown
    > OnKeyUP

    ну - попробуй onkeypress до кучи
    if( key = ^c )then begin
      ...
      key: = #0;
    end;
  • allrussia (21.05.10 17:11) [8]

    > Эмн... а к чему эта фраза, да еще и выделенная ?
    > Разве данные операции работают не через SetClipboardData,
    >  EmptyClipboard ?


    спасибо, вот что удалось надыбать

    function NewMemoProc(wnd:HWND; uMsg:UINT; wParam:WPARAM; lParam:LPARAM):integer; stdcall;
    begin
    if (uMsg = WM_CUT) or (uMsg = WM_COPY) then uMsg := 0;
    result:=CallWindowProc(Pointer(GetWindowLong(wnd,GWL_USERDATA)),wnd,uMsg,wParam, lParam)
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    SetWindowLong(Memo1.Handle,GWL_USERDATA,SetWindowLong(Memo1.Handle, GWL_WNDPROC, LPARAM(@NewMemoProc)))
    end;



    собственно вопрос:

    1. как сделать чтобы применялось для всех edit-, memo-, text-контролов?
    2. корректен ли этот код и можно ли избежать такой громоздкости?

    for i:= 0 to ComponentCount -1 do
    SetWindowLong(component[i].handle,GWL_USERDATA,SetWindowLong(component[i].handle , GWL_WNDPROC, LPARAM(@NewMemoProc)))
  • allrussia (21.05.10 17:22) [9]
    han_malign

    спасибо вариант хороший, но
    1 проблема: когда отпускаешь первым Ctrl начинают вводиться буквы  'C'

    2 придется русками везде  прописывать на всех контролах и ctrl +C и Ctrl+X (с отловом позиции курсора, а ведь есть еще ctrl+Ins и пр...) + проблема 1
  • Игорь Шевченко © (21.05.10 19:49) [10]
    тебе надо перехватывать WM_COPY.

    В древнем Китае желающим странного отрубали голову. Весьма эффективный метод, надо признать.
  • allrussia (21.05.10 19:54) [11]

    > Игорь Шевченко ©   (21.05.10 19:49) [10]
    >
    > тебе надо перехватывать WM_COPY.


    не тебе, а вам. спасибо за экскурс в историю

    а это что (21.05.10 17:11) [8],не перехват WM_COPY?
    Появились другие вопросы в [8] и [9].
  • Игорь Шевченко © (21.05.10 19:58) [12]
    allrussia   (21.05.10 19:54) [11]


    > не тебе, а вам


    а нам это нафиг не сдалось


    > корректен ли этот код и можно ли избежать такой громоздкости?


    Для решения тупой задачи вполне годится такой тупой код.

    Но гораздо проще надписать компоненты и в них заменять оконную процедуру на нужную (как это неоднократно демонстрируется в stdctrls.pas)
  • allrussia (21.05.10 20:04) [13]

    Игорь Шевченко
    > Для решения тупой задачи вполне годится такой тупой код.

    поясните, почему тупой... вы не пользуетесь CTRL+C,CTRL+V? :))

    в целом задача такова:
    корректное копирование русского текста в буфер при нажатии комбинации клавиш CTR+C, Ins в Vista, 7, 2008 из контролов Delphi, не поддерживающих юникод
  • Игорь Шевченко © (21.05.10 20:27) [14]
    allrussia   (21.05.10 20:04) [13]


    > в целом задача такова:
    > корректное копирование русского текста в буфер


    http://www.sql.ru/forum/actualthread.aspx?tid=244851
    http://www.delphikingdom.com/asp/viewitem.asp?catalogid=780

    тоже способ предлагают, без перехвата.
  • allrussia (21.05.10 20:32) [15]
    Игорь Шевченко

    > тоже способ предлагают, без перехвата.


    спасибо, но у меня оба эти линка постоянно открыты :) и не только эти, а еше как минимум 3 способа
    RUSClip - например ничего не дает и не обрабатывается
    вручную (например через попап меню) скопировать корректно текст не проблема

    основная проблема заключается в перехвате CTRL+C
  • Игорь Шевченко © (21.05.10 20:43) [16]
    allrussia   (21.05.10 20:32) [15]

    Проблема заключается в том, чтобы установить корректную кодовую страницу в Clipboard. Перехватывать кучу клавиатурных комбинаций - это не всегда и не совсем удобно.

    Можно конечно пробегаться по формам и переустанавливать оконные процедуры, но типов контролов много (кстати, сами формы (RTFS: Dialogs.TMessageForm) тоже могут быть скопированы по Ctrl+C, не только Edit-ы и их производные, и результаты копирования подчиняются тем же правилам кодовой страницы) и для каждого переопределять оконную процедуру, мягко говоря, не очень разумно.

    Если перехватывать, то лучше надписывать компоненты (можно по способу Geo http://www.interface.ru/home.asp?artId=16753)

    и в их обработчике WM_COPY, WM_CUT устанавливать нужную кодовую страницу.
  • Leonid Troyanovsky © (21.05.10 20:59) [17]

    > allrussia   (21.05.10 16:25) [5]

    > Вы вопрос поняли? Мне нужно чтобы по нажатию Ctrl+C на любом
    > контроле вистема не копировала содержимое в буфер обмена.
    >  (Это примерно то же самое что перехват Ctrl+Alt+Del, просто

    Вопрос мы поняли. Не надо - не копируй.
    Хотя, про любой - это, дейс-но, новость.

    Перехватом же Ctrl+Alt+Del мы и не заморачиваемся.

    --
    Regards, LVT.
  • allrussia (21.05.10 22:51) [18]
    Игорь Шевченко


    > Проблема заключается в том, чтобы установить корректную
    > кодовую страницу в Clipboard.


    Это я знаю и добиваюсь.

    Перехватывать кучу клавиатурных комбинаций - это не всегда и не совсем удобно.


    Неудобно. Но рука тянется к клавишам, а не ПКМ. Хочется нормальный русский текст по CTRL+C.


    > Если перехватывать, то лучше надписывать компоненты (можно
    > по способу Geo http://www.interface.ru/home.asp?artId=16753)
    >


    как "надписывание" поможет перехватить CTRL+С?

    вы можете показать хоть 1 рабочий пример, где происходит корректное копирование/вставка в/из Memo в/из буфер обмена с помощью системных комбинаций клавиш Ctrl,Shift,C,Ins?

    вот так?


    procedure TForm1.WndProc (var message: TMessage);
    begin
     if (message.Msg = WM_COPY) or (message.Msg = WM_CUT) then
       {????????}
     else
       inherited
    end;



    тишина
  • Игорь Шевченко © (21.05.10 23:16) [19]
    allrussia   (21.05.10 22:51) [18]


    > вы можете показать хоть 1 рабочий пример, где происходит
    > корректное копирование/вставка в/из Memo в/из буфер обмена
    > с помощью системных комбинаций клавиш Ctrl,Shift,C,Ins?


    Могу показать 1 пример:

     TForm1 = class(TForm)
       Edit1: TEdit;
       Memo1: TMemo;
     private
       FOldMemoWndProc: TWndMethod;
       FOldEditWndProc: TWndMethod;
       procedure MemoWndProc (var Message: TMessage);
       procedure EditWndProc (var Message: TMessage);
     end;

    var
     Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.FormCreate(Sender: TObject);
    begin
     FOldMemoWndProc := Memo1.WindowProc;
     Memo1.WindowProc := MemoWndProc;
     FOldEditWndProc := Edit1.WindowProc;
     Edit1.WindowProc := EditWndProc;
     Memo1.Lines.Text := 'Это русский текст';
    end;

    procedure TForm1.MemoWndProc(var Message: TMessage);
    var
     LKL: array [0..1023] of char;
    begin
     if Message.Msg = WM_COPY then
     begin
       GetKeyboardLayoutName(LKL);
       LoadKeyboardLayout('00000419',KLF_ACTIVATE);
     end;
     FOldMemoWndProc(Message);
     if Message.Msg = WM_COPY then
       LoadKeyboardLayout(LKL,KLF_ACTIVATE);
    end;

    procedure TForm1.EditWndProc(var Message: TMessage);
    var
     LKL: array [0..1023] of char;
    begin
     if Message.Msg = WM_COPY then
     begin
       GetKeyboardLayoutName(LKL);
       LoadKeyboardLayout('00000419',KLF_ACTIVATE);
     end;
     FOldEditWndProc(Message);
     if Message.Msg = WM_COPY then
       LoadKeyboardLayout(LKL,KLF_ACTIVATE);
    end;



    В случае надписанного же компонента в его обработчике сообщений
    WM_COPY/WM_CUT будет такая же операция мамбл-ванго, как в примере, вызов inherited для обработки сообщения родным контролом и восстановление раскладки.
 
Конференция "WinAPI" » Ctrl+C - запрет ОС на копирование в буфер обмена [D7, WinXP]
Есть новые Нет новых   [118430   +14][b:0][p:0.002]