Použití Drag and Drop v C++ Builderu

Většina sofistikovanějších programů běžně podporuje techniku „drag and drop“. Ukážeme si, jak ji aplikovat v C++ Builderu.
Vytvoříme si novou aplikaci s jedním formulářem, na který umístíme list-box (TListBox) a víceřádkový edit (Tmemo). Budeme chtít aby při přetažení jednoho nebo více souborů do list-boxu se názvy těchto souborů přidaly do seznamu list-boxu. V případě editu pak budeme chtít zobrazit obsah textového souboru přetaženého do tohoto editu.

Výsledek vidíte na obrázku:

Klepněte pro větší obrázek

Jak na to?

Aby příslušné okno vůbec bylo schopno přijímat přetažené souboru musíme tuto vlastnost nejprve aktivovat pomocí (API) funkce DragAcceptFiles:

VOID DragAcceptFiles(
  HWND hWnd, // handle okna
  BOOL fAccept // povolení přijímání souborů
);

Jak je zřejmé, touto funkcí můžeme totéž samozřejmě opět zakázat.

Dále je potřeba vědět, že při „puštění“ taženého souboru do okna, které má tuto vlastnost povolenu, dostane toto okno zprávu WM_DROPFILES, z jejichž parametrů budeme moci zjistit vše potřebné. Vzhledem k tomu, že chceme nezávisle reagovat na přetažení u dvou různých komponent, a u každé provést trochu jinou „akci“, nebudeme tuto zprávu zachytávat globálně ve formuláři, ale zvlášť pro každý prvek, tedy list-box a víceřádkový edit. Musíme proto nějak vytvořit handleny zprávy WM_DROPFILES pro tyto prvky. Nejpřímější cesta je přes proceduru okna. Vytvoříme si tedy 2 funkce, odpovídající svojí „kostrou“ proceduře okna tak, jak je zapouzdřena ve VCL, a na tyto funkce nastavíme procedury okna našich 2 prvků pomocí property WindowProc.

__property TWndMethod WindowProc = {read=FWindowProc, write=FWindowProc};

Před tím si musíme uložit původní „hodnotu“ procedury okna, neboť tuto musíme v naší vlastní proceduře volat pro defaultní zpracování zpráv. Tyto hodnoty si tedy uložíme do následujících proměnných příslušného typu:

TWndMethod oldProcMemo;
TWndMethod oldProcList;

Celé přesměrování a výše uvedené povolení příjímání souborů můžeme provést například v události OnCreate formuláře:

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  DragAcceptFiles(ListBox1->Handle, TRUE);
  DragAcceptFiles(Memo1->Handle, TRUE);
  oldProcMemo = Memo1->WindowProc;
  Memo1->WindowProc = WndProcMemo;
  oldProcList = ListBox1->WindowProc;
  ListBox1->WindowProc = WndProcList;
}

Nyní již budeme moci snadno zachytit libovolnou zprávu těmto prvkům včetně té, která nás zajímá, tedy WM_DROPFILES. Tato zpráva má ve svém parametru wParam handle interní struktury, popisující přetažené soubory. Tento handle pak použijeme jako 1. parametr ve funkci DragQueryFile:

UINT DragQueryFile(
  HDROP hDrop,
  UINT iFile,
  LPTSTR lpszFile,
  UINT cch
);

Druhým parametrem (idole) této funkce je index na požadovaný soubor, jehož jméno nám funkce vloží do bufferu lpszFile (3. parametr). Parametr cch je pak velikost bufferu lpszFile.

Dále musíme vědět, jak zjistit počet přetažených souborů. Opět použijeme funkci DragQueryFile, s tím že jako parametr idole zadáme 0xFFFFFFFF a lpszFile NULL. Parametr cch je pak samozřejmě 0. Po „zpracování“ musíme ještě uvolnit paměť, kterou nám systém alokoval pro přenos informací o souborech. To provedeme funkcí DragFinish:

VOID DragFinish(
  HDROP hDrop
);

Podívejme se tedy, jak vypadá kompletní procedura okna list boxu, ve které přetažené soubory přidáme do položek list-boxu:

void __fastcall TForm1::WndProcList(Messages::TMessage &Message)
{
  HDROP hdrop;
  int count;
  TCHAR chFile[_MAX_PATH];
  switch ( Message.Msg )
  {
    case WM_DROPFILES:
      hdrop = (HDROP)Message.WParam;
      count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
      for ( int i = 0; i < count; i++ )
      {
        DragQueryFile(hdrop, i, chFile, _MAX_PATH);
        SendMessage(ListBox1->Handle, LB_ADDSTRING, 0,
          (LPARAM)chFile);
      }
      DragFinish(hdrop);
      Application->Restore();
      ShowWindow(Application->Handle, SW_RESTORE);
      SetForegroundWindow(Application->Handle);
      break;
  }
  oldProcList(Message); // voláme původní proceduru okna
}

Pro přidání položky list-boxu jsem použil zprávu LB_ADDSTRING, což je jednodušší a rychlejší než převádět získané jméno souboru na AnsiString a ten pak přidat pomocí metody Add přes property Items list-boxu.

U načtení obsahu přetaženého souboru si situaci zjednodušíme tak, že budeme „defaultně“ brát soubor s indexem 0 i v případě většího počtu souborů. Nebyl by samozřejmě problém doprogramovat to tak, aby se obsah souboru do editu přidal, a bude souborů víc aby byly zpracovány všechny. Pro načtení souboru použijeme metodu LoadFromFile property Lines třídy TMemo.

void __fastcall TForm1::WndProcMemo(Messages::TMessage &Message)
{
  HDROP hdrop;
  TCHAR chFile[_MAX_PATH];
  AnsiString as;
  switch ( Message.Msg )
  {
    case WM_DROPFILES:
      hdrop = (HDROP)Message.WParam;
      DragQueryFile(hdrop, 0, chFile, _MAX_PATH);
      as = AnsiString(chFile);
      Memo1->Lines->LoadFromFile(as);
      DragFinish(hdrop);
      Application->Restore();
      ShowWindow(Application->Handle, SW_RESTORE);
      SetForegroundWindow(Application->Handle);
      break;
  }
  oldProcMemo(Message);
}

Ukázkový příklad si můžete stáhnout zde drag_and_drop.zip.

Váš názor Další článek: Další detaily ohledně Geforce 4

Témata článku: Software, Programování, Message, Drag, Drag and drop, Idol, Lines, Potřebné povolení, Použití, DRO


Určitě si přečtěte

Air Bank, Fio banka a MONETA zakládají alianci pro bankovní identitu
Jakub Čížek
BankaČeskoeGovernment
Nejlepší notebooky do 20 000 Kč. Tipy, co se dnes vyplatí koupit

Nejlepší notebooky do 20 000 Kč. Tipy, co se dnes vyplatí koupit

** S cenou do 20 tisíc lze vybrat solidní notebook na práci i hry ** Přenosné notebooky nabídnou i kovová těla a rychlý hardware ** Možná největší problém je nedostupnost, nejžádanější kusy jsou vyprodané

David Polesný | 33

David Polesný
VánoceNotebooky
WhatsApp konečně umožní smazat velké soubory z konverzací, aby nezabíraly místo
Vladislav Kluska
WhatsAppFacebookInstant Messaging
Elon Musk podpořil Signal jako náhradu WhatsAppu. Aplikaci okamžitě zavalili uživatelé
Markéta Mikešová
WhatsAppElon MuskFacebook
Nejlepší příslušenství k počítači. Tipy na osvědčené klávesnice, tiskárny, routery…

Nejlepší příslušenství k počítači. Tipy na osvědčené klávesnice, tiskárny, routery…

** Tipy na užitečné příslušenství k počítačům ** Poradíme, s jakými produkty neuděláte chybu ** Některé z věcí mohou být dobrými vánočními dárky

David Polesný, Stanislav Janů | 20

David PolesnýStanislav Janů
Příslušenství
Lidl buduje chytrou domácnost, propojí všechno se vším
Lukáš Václavík
LidlChytrá domácnostIoT
Testy procesorů Ryzen 5000: AMD překonalo Intel ve všech směrech

Testy procesorů Ryzen 5000: AMD překonalo Intel ve všech směrech

** AMD začalo prodávat nové procesory Ryzen 5000 s architekturou Zen 3 ** K dispozici jsou nezávislé testy z celého světa ** AMD překonává Intel ve všech směrech

Karel Javůrek | 69

Karel Javůrek
ProcesoryTestyAMD
Nejlepší notebooky do 10 000 korun: Co má ještě smysl kupovat. A co ne?

Nejlepší notebooky do 10 000 korun: Co má ještě smysl kupovat. A co ne?

** Notebooky s cenou do deseti tisíc korun jsou plné kompromisů ** Existuje několik modelů dobře použitelných pro nenáročné použití ** Vhodnou alternativou jsou tablety nebo repasované počítače

David Polesný | 94

David Polesný
Jak vybrat notebookNotebooky

Aktuální číslo časopisu Computer

Jak prodloužit výdrž notebooku

Velké testy: gamepady a inkoustové tiskárny

Důkladný test Sony Playstation 5