Jump to content


Photo

[MULTILENGUAJE] Como Copiar Campos de un TListView

TListView Copy

  • Please log in to reply
3 replies to this topic

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 13 July 2018 - 07:19 AM

Se me ha presentado la necesidad de poder copiar campos (SubItems) de un TListView y dado que la aplicación tiene muchos controles de ese tipo, decidí hacer un sistema sencillo de adaptar a los formularios, que tengan el citado componente y que me ahorrase reescribir código. La solución que he implementado es una clase que realiza un subclassing del ListView y le introduce un PopupMenu con la opción "copy". Si ya existía un menú previo asignado al ListView puede utilizar éste. El código de la clase está escrito primeramente en C++ y con API, de esta forma se puede adaptar a aplicaciones No VCL. Pero no os preocupéis, he hecho una traducción a delphi.
 
Para dejar claro que se ha hecho la copia del campo seleccionado, aparece un marquito en su borde durante 300 ms.
Es necesario incluir un archivo de recursos estilo WinXP
 
0ad6b274ab935542d16a8bb0b60ba0d1o.gif
 
Vamos a exponer el código que está probado para delphi 6, 7 y Berlin.


delphi
  1. unit ListViewCopy;
  2.  
  3. //------------------------------------------------------------------------------
  4. // TLVCopy  V 3.0
  5. // escafandra 2018
  6. // Clase para permitir copiar al portapapeles un campo de texto de un ListView
  7. // tipo vsReport, visualiza el contorno del campo del Item copiado
  8. // Incluir recursos estilo WinXP
  9.      
  10.  
  11. interface
  12.  
  13. uses Windows, Messages, CommCtrl;
  14.  
  15. type
  16.  
  17. {$IfnDef TLVITEMINDEX}
  18. TLVITEMINDEX = record
  19.   iItem: integer;
  20.   iGroup: integer;
  21. end;
  22. PLVITEMINDEX = ^TLVITEMINDEX;
  23. {$EndIf}
  24.  
  25. TLVCopy = class
  26.   private
  27.     hListView: THANDLE;
  28.     Window: THANDLE;
  29.     OldListViewProc: Pointer;
  30.     Menu: HMENU ;
  31.     Point: TPOINT ;
  32.     ItemIndex: integer;
  33.     MenuIndex: integer;
  34.     DeleteMenu: boolean;
  35.  
  36.     function ListViewProc(Handle: HWND; Msg: DWORD; WParam: DWORD; LParam: DWORD): DWORD; stdcall;
  37.     function CopyText(Text: PAnsiChar): boolean;
  38.   public
  39.     destructor Destroy; override;
  40.     procedure  SetHandle(Handle: THANDLE; Text: PAnsiCHAR = nil; _menu: HMENU = 0; _menuIndex: integer = 0; Win: THANDLE = 0);
  41.     procedure  Copy();
  42. end;
  43.  
  44. const
  45. LVM_GETITEMINDEXRECT = (LVM_FIRST + 209);
  46.  
  47. implementation
  48.  
  49. function ListView_GetColumnCount(hListView: THANDLE): integer;
  50. var
  51.   hHdr: HWND;
  52. begin
  53.   hHdr:= SendMessage(hListView, LVM_GETHEADER, 0, 0);
  54.   Result:= SendMessage(hHdr, HDM_GETITEMCOUNT, 0, 0);
  55. end;
  56.  
  57. function ListView_HitTest(hListView: THANDLE; var IInfo: TLVHITTESTINFO): integer;
  58. begin
  59.   Result:= SendMessage(hListView, LVM_HITTEST, 0, integer(@IInfo));
  60. end;
  61.  
  62. function ListView_GetItemIndexRect(hListView: THANDLE; var lvii: TLVITEMINDEX; SubItem, Code: cardinal; var Rect: TRect): integer;
  63. begin
  64.   Rect.Top:= SubItem;
  65.   Rect.Left:= Code;
  66.   Result:= SendMessage(hListView, LVM_GETITEMINDEXRECT, Cardinal(@lvii), cardinal(@Rect));
  67. end;
  68.  
  69. function GetItemAndSubItem(hListView: THANDLE; X, Y: integer; var SubItem: integer): integer;
  70. var
  71.   IInfo: TLVHITTESTINFO;
  72.   ItemIndex, Columns, ComentLeft: integer;
  73. begin
  74.   IInfo.pt.x:= 5;
  75.   IInfo.pt.y:= Y;
  76.   ItemIndex:= ListView_HitTest(hListView, IInfo);
  77.  
  78.   Columns:= ListView_GetColumnCount(hListView);
  79.   ComentLeft:= 0;
  80.   SubItem:= -1;
  81.   repeat
  82.     inc(SubItem);
  83.     ComentLeft:= ComentLeft + ListView_GetColumnWidth(hListView, SubItem);
  84.   until (X < ComentLeft) or (SubItem >= Columns - 1);
  85.  
  86.   if X > ComentLeft then SubItem:= -1;
  87.   Result:= ItemIndex;
  88. end;
  89.  
  90. // SubItem = 0 para Caption
  91. function GetRect(hListView: THANDLE; ItemIndex, SubItem: integer): TRect;
  92. var
  93.   lvii: TLVITEMINDEX;
  94. begin
  95.   lvii.iItem:= ItemIndex;
  96.   ListView_GetItemIndexRect(hListView, lvii, SubItem, LVIR_BOUNDS, Result);
  97.   if SubItem = 0 then
  98.     Result.right:= Result.left + ListView_GetColumnWidth(hListView, 0);
  99. end;
  100.  
  101. //---------------------------------------------------------------------------
  102. // SubItem = 0 para Caption
  103. procedure DrawFrameRect(hListView: THANDLE; ItemIndex, SubItem: integer; Color: TCOLORREF);
  104. var
  105.   R: TRect;
  106.   DC: HDC;
  107.   Pen: HPEN;
  108. begin
  109.   R:= GetRect(hListView, ItemIndex, SubItem);
  110.   DC:= GetDC(hListView);
  111.   Pen:= CreatePen(PS_SOLID, 3, Color);
  112.   SelectObject(DC, GetStockObject(NULL_BRUSH));
  113.   SelectObject(DC, Pen);
  114.   Rectangle(DC, R.left, R.top, R.right, R.bottom);
  115.   DeleteObject(Pen);
  116.   ReleaseDC(hListView, DC);
  117. end;
  118.  
  119. procedure TLVCopy.Copy;
  120. var
  121.   Item: TLVITEMA;
  122.   Si: integer;
  123.   R: TRect;
  124.   Buffer: array [0..511] of AnsiCHAR;
  125. begin
  126.   // Obtengo ItemIndex y SubItem
  127.   ItemIndex:= GetItemAndSubItem(hListView, Point.x, Point.y, Si);
  128.  
  129.   // Leyendo el texto a copiar
  130.   Item.iItem:= ItemIndex;
  131.   Item.iSubItem:= Si;
  132.   Item.pszText:= Buffer;
  133.   Item.cchTextMax:= sizeof(Buffer);
  134.  
  135.   // Copiando al ClipBoard y pintando el marco
  136.   if SendMessage(hListView, LVM_GETITEMTEXTA, ItemIndex, integer(@Item))>0 then
  137.   begin
  138.     // Copiando al ClipBoard
  139.     if CopyText(Buffer) then
  140.     begin
  141.       // Pintando el marco para confirmar
  142.       DrawFrameRect(hListView, ItemIndex, Si, $FFFF00);
  143.       Sleep(300);
  144.       R:= GetRect(hListView, ItemIndex, Si);
  145.       InflateRect(R, 1, 1);
  146.       InvalidateRect(hListView, @R, true);
  147.     end;
  148.   end;
  149. end;
  150.  
  151. function DefListViewProc(Handle: HWND; Msg: DWORD; WParam: DWORD; LParam: DWORD): DWORD; stdcall;
  152. var
  153.   pLVCopy: TLVCopy;
  154. begin
  155.   pLVCopy:= TLVCopy(GetWindowLong(Handle, GWL_USERDATA));
  156.   if pLVCopy <> nil then
  157.     Result:= pLVCopy.ListViewProc(Handle, Msg, WParam, LParam)
  158.   else
  159.     Result:= DefWindowProc(Handle, Msg, WParam, LParam);
  160. end;
  161.  
  162. function TLVCopy.ListViewProc(Handle: HWND; Msg: DWORD; WParam: DWORD; LParam: DWORD): DWORD; stdcall;
  163. var
  164.   ScrPoint: TPoint;
  165.   Si, Item: integer;
  166. begin
  167.   if Msg = WM_CONTEXTMENU then
  168.   begin
  169. //    ScrPoint.x:= LParam and $FFFF;
  170. //    ScrPoint.y:= LParam shr 16;
  171.     GetCursorPos(ScrPoint);
  172.     Point:= ScrPoint;
  173.     ScreenToClient(Handle, Point);
  174.     Item:= GetItemAndSubItem(hListView, Point.x, Point.y, Si);
  175.     if (Item >= 0) and (Si>=0) then
  176.     begin
  177.       TrackPopupMenuEx(Menu, 0, ScrPoint.x, ScrPoint.y, hListView, nil);
  178.       Result:= DefWindowProc(Handle, Msg, WParam, LParam);
  179.       Exit;
  180.     end;
  181.   end
  182.   else if Msg = WM_COMMAND then
  183.   begin
  184.     if WParam = cardinal(MenuIndex) then
  185.       Copy;   // Copio el campo al portapapeles
  186.     if (WParam and $0000FFFF) <> 0 then
  187.       // Se rebota el mensaje para que la ventana de tratamiento del menú ya existente
  188.       // pueda tratar el comando
  189.       PostMessage(Window, WM_COMMAND, WParam, 0);
  190.   end;
  191.   Result:= CallWindowProc(OldListViewProc, Handle, Msg, WParam, LParam);
  192. end;
  193.  
  194. // Cuando ya se dispone de un menú, se puede usar pasando su Handle, el Index para
  195. // activar el Copy y la ventana de tratamiento de mensajes del menú existente
  196. procedure TLVCopy.SetHandle(Handle: THANDLE; Text: PAnsiCHAR = nil; _menu: HMENU = 0; _menuIndex: integer = 0; Win: THANDLE = 0);
  197. begin
  198.   if (hListView <> 0) or (Handle = INVALID_HANDLE_VALUE) or (Handle = 0) then
  199.   if hListView <> 0 then
  200.   begin
  201.     SetWindowLong(hListView, GWL_USERDATA, 0);
  202.     SetWindowLong(hListView, GWL_WNDPROC, LongInt(OldListViewProc));
  203.     hListView:= 0;
  204.     if DeleteMenu then DestroyMenu(Menu);
  205.   end;
  206.  
  207.   if (Handle <> INVALID_HANDLE_VALUE) and (Handle <> 0) then
  208.   begin
  209.     hListView:= Handle;
  210.     SetWindowLong(hListView, GWL_USERDATA, LongInt(self));
  211.     OldListViewProc:= Pointer(SetWindowLong(hListView, GWL_WNDPROC, LongInt(@DefListViewProc)));
  212.     if _menu <> INVALID_HANDLE_VALUE then
  213.     begin
  214.       if _menu <> 0 then
  215.       begin
  216.         Menu:= _menu;
  217.         Window:= Win;
  218.         MenuIndex:= _menuIndex;
  219.         DeleteMenu:= false;
  220.         if Text <> nil then
  221.           InsertMenuA(Menu, 0, MF_POPUP or MF_BYPOSITION, MenuIndex, Text);
  222.       end else
  223.       begin
  224.         Menu:= CreatePopupMenu();
  225.         MenuIndex:= 0;
  226.         if Text <> nil then
  227.           InsertMenuA(Menu, 0, MF_POPUP, MenuIndex, Text)
  228.         else
  229.           InsertMenuA(Menu, 0, MF_POPUP, MenuIndex, 'Copiar Campo');
  230.         DeleteMenu:= true;
  231.       end;
  232.     end;
  233.   end;
  234. end;
  235.  
  236. function TLVCopy.CopyText(Text: PAnsiCHAR): boolean;
  237. var
  238.   clBuffer: HGLOBAL;
  239.   GBuffer: PAnsiCHAR;
  240. begin
  241.   Result:= OpenClipboard(hListView);
  242.   if Result then
  243.   begin
  244.     EmptyClipboard();
  245.     clBuffer:= GlobalAlloc(GMEM_DDESHARE, lstrlenA(Text)+1);
  246.     GBuffer:= GlobalLock(clBuffer);
  247.     lstrcpyA(GBuffer, Text);
  248.     GlobalUnlock(clBuffer);
  249.     SetClipboardData(CF_TEXT, clBuffer);
  250.     CloseClipboard();
  251.   end;
  252. end;
  253.  
  254.  
  255. destructor TLVCopy.Destroy;
  256. begin
  257.   SetHandle(0);
  258. end;
  259.  
  260. end.

La forma de uso es bien sencilla, se precisa una instancia TLVCopy por cada TListView al que queramos dotar de la opción copy. A la instancia se le asigna el Handle del TListView y listo:


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, ComCtrls, ListViewCopy;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. ListView: TListView;
  12. procedure FormCreate(Sender: TObject);
  13. private
  14. LVCopy: TLVCopy;
  15. public
  16. { Public declarations }
  17. end;
  18.  
  19. var
  20. Form1: TForm1;
  21.  
  22. implementation
  23.  
  24. {$R *.dfm}
  25.  
  26. procedure TForm1.FormCreate(Sender: TObject);
  27. begin
  28. LVCopy:= TLVCopy.Create;
  29. LVCopy.SetHandle(ListView.Handle);
  30. end;
  31.  
  32. procedure TForm1.FormDestroy(Sender: TObject);
  33. begin
  34.   LVCopy.Free;
  35. end;
  36.  
  37. end.

Para que el código sea compatible en versiones antiguas, he optado por descartar UNICODE aunque esto es transparente al uso de la clase, es importante decirlo por si alguno quiere meterle mano.
 
 
Características:
1. Usa la técnica del subclassing con API pura.
2. Cada Instancia controla un TListView.
3. Crea un PopupMenu con la opción de copiar.
4. Una vez copiado el texto, remarca el campo con un marquito durante 300 ms.
5. El Texto del Item del menú se puede personalizar.
6. Si ya existe un menú previo, se puede pasar como parámetro y elegir si LVCopy añade el Item al menú o lo añadimos nosotros. También pasaremos el valor Item.Comand del MenuItem.
7. Usa Texto no Unicode.
8. La versión delphi requiere destruir la instancia, no así la C++, a no ser que esté creada como un puntero.
 
 
Saludos.


  • 2

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 13 July 2018 - 07:34 AM

La versión C++ es la madre de la criatura y dado a que la clase no es un componente, la instancia creada no se trata como un puntero con lo que no se precisa destruirla. La funcionalidad es la misma que la versión delphi y también desecha UNICODE. Está probada en C++ Builder 5 y Berlin.


cpp
  1. //------------------------------------------------------------------------------
  2. // TLVCopy V 3.0
  3. // escafandra 2018
  4. // Clase para permitir copiar al portapapeles un campo de texto de un ListView
  5. // tipo vsReport, visualiza el contorno del campo del Item copiado
  6. // Incluir recursos estilo WinXP
  7.      
  8. #ifndef ListViewCopyH
  9. #define ListViewCopyH
  10.  
  11.  
  12. #include <Windows.h>
  13. #include <Windowsx.h>
  14. #include <commctrl.h>
  15.  
  16. #ifndef STRICT
  17.   typedef int  (__stdcall *PLRESULT)();
  18. #else
  19.   typedef WNDPROC PLRESULT;
  20. #endif
  21.  
  22. //---------------------------------------------------------------------------
  23. #ifndef LVM_GETITEMINDEXRECT
  24. typedef struct tagLVITEMINDEX {
  25.   int iItem;
  26.   int iGroup;
  27. } LVITEMINDEX, *PLVITEMINDEX;
  28. #define LVM_GETITEMINDEXRECT    (LVM_FIRST + 209)
  29. #define ListView_GetItemIndexRect(hwnd, plvii, iSubItem, code, prc) \
  30.         (BOOL)SNDMSG((hwnd), LVM_GETITEMINDEXRECT, (WPARAM)(LVITEMINDEX*)(plvii), \
  31.                 ((prc) ? ((((LPRECT)(prc))->top = (iSubItem)), (((LPRECT)(prc))->left = (code)), (LPARAM)(prc)) : (LPARAM)(LPRECT)NULL))
  32. #endif
  33.  
  34. class TLVCopy
  35. {
  36.   private:
  37.   HWND  hListView;
  38.   HWND  Window;
  39.   HMENU hMenu;
  40.   PLRESULT OldListViewProc;
  41.   POINT Point;
  42.   int ItemIndex;
  43.   int MenuIndex;
  44.   BOOL DeleteMenu;
  45.  
  46.   BOOL CopyText(char* Text);
  47.   static LRESULT __stdcall DefListViewProc(HWND hWnd, UINT Msg, WPARAM WParam, LPARAM LParam);
  48.   LRESULT __stdcall ListViewProc(HWND hWnd, UINT Msg, WPARAM WParam, LPARAM LParam);
  49.  
  50.   public:
  51.   void SetHandle(HWND HListView, char *Text = 0, HMENU hmenu = 0, int menuIndex = 0, HWND hWnd = 0);
  52.   void Copy();
  53.   ~TLVCopy();
  54. };
  55.  
  56. #endif


cpp
  1. //------------------------------------------------------------------------------
  2. // TLVCopy  V 3.0
  3. // escafandra 2018
  4. // Clase para permitir copiar al portapapeles un campo de texto de un ListView
  5. // tipo vsReport, visualiza el contorno del campo del Item copiado
  6. // Incluir recursos estilo WinXP
  7.      
  8. #include "ListViewCopy.h"
  9.  
  10. int ListView_GetColumnCount(HWND hListView)
  11. {
  12.   HWND hHdr = (HWND)SendMessage(hListView, LVM_GETHEADER, 0, 0);
  13.   return SendMessage(hHdr, HDM_GETITEMCOUNT, 0, 0L);
  14. }
  15.  
  16. int GetItemAndSubItem(HWND hListView, int X, int Y, int *SubItem)
  17. {
  18.   LVHITTESTINFO IInfo;
  19.   IInfo.pt.x = 5;
  20.   IInfo.pt.y = Y;
  21.   int ItemIndex = ListView_HitTest(hListView, &IInfo);
  22.  
  23.   if(SubItem){
  24.     int Columns = ListView_GetColumnCount(hListView);
  25.     int ComentLeft = 0;
  26.     for(*SubItem = -1; *SubItem + 1 < Columns && X >= ComentLeft; ++*SubItem)
  27.       ComentLeft += ListView_GetColumnWidth(hListView, *SubItem + 1);
  28.     if(X > ComentLeft) *SubItem = -1;
  29.   }
  30.   return ItemIndex;
  31. }
  32.  
  33. // SubItem = 0 para Caption
  34. RECT GetRect(HWND hListView, int ItemIndex, int SubItem)
  35. {
  36.   RECT Result;
  37.   LVITEMINDEX lvii;
  38.   lvii.iItem = ItemIndex;
  39.   ListView_GetItemIndexRect(hListView, &lvii, SubItem, LVIR_BOUNDS, &Result);
  40.   if(SubItem == 0)
  41.     Result.right = Result.left + ListView_GetColumnWidth(hListView, 0);
  42.   return Result;
  43. }
  44.  
  45. //---------------------------------------------------------------------------
  46. // SubItem = 0 para Caption
  47. void DrawFrameRect(HWND hListView, int ItemIndex, int SubItem,  COLORREF Color)
  48. {
  49.   RECT R = GetRect(hListView, ItemIndex, SubItem);
  50.   HDC hDC = GetDC(hListView);
  51.   HPEN hPen = CreatePen(PS_SOLID, 3, Color);
  52.   SelectObject(hDC, GetStockObject(NULL_BRUSH));
  53.   SelectObject(hDC, hPen);
  54.   Rectangle(hDC, R.left, R.top, R.right, R.bottom);
  55.   DeleteObject(hPen);
  56.   ReleaseDC(hListView, hDC);
  57. }
  58.  
  59. //---------------------------------------------------------------------------
  60.  
  61.  
  62.  
  63. //---------------------------------------------------------------------------
  64. // Clase TLVCopy
  65. BOOL TLVCopy::CopyText(CHAR* Text)
  66. {
  67.   if(OpenClipboard(hListView)){
  68.     EmptyClipboard();
  69.     HGLOBAL clBuffer = GlobalAlloc(GMEM_DDESHARE, lstrlenA(Text)+1);
  70.     char* GBuffer = (char*)GlobalLock(clBuffer);
  71.     lstrcpyA(GBuffer, Text);
  72.     GlobalUnlock(clBuffer);
  73.     SetClipboardData(CF_TEXT, clBuffer);
  74.     CloseClipboard();
  75.     return true;
  76.   }
  77.   return false;
  78. }
  79.  
  80. //---------------------------------------------------------------------------
  81. // Copia un campo del ListView identificado por la posición del mouse
  82. void TLVCopy::Copy()
  83. {
  84.   // Obtengo ItemIndex y SubItem
  85.   int Si;
  86.   ItemIndex = GetItemAndSubItem(hListView, Point.x, Point.y, &Si);
  87.  
  88.   // Leyendo el texto a copiar
  89.   char Buffer[512];
  90.   LVITEMA Item;
  91.   Item.iItem = ItemIndex;
  92.   Item.iSubItem = Si;
  93.   Item.pszText = Buffer;
  94.   Item.cchTextMax = sizeof(Buffer);
  95.   int n = SendMessage(hListView, LVM_GETITEMTEXTA, ItemIndex, (LPARAM)&Item);
  96.  
  97.   // Copiando al ClipBoard y pintando el marco
  98.   if(n){
  99.     // Copiando al ClipBoard
  100.     if(CopyText(Buffer)){
  101.       // Pintando el marco para confirmar
  102.       DrawFrameRect(hListView, ItemIndex, Si, 0xFFFF00);
  103.       Sleep(300);
  104.       RECT R = GetRect(hListView, ItemIndex, Si);
  105.       InflateRect(&R, 1, 1);
  106.       InvalidateRect(hListView, &R, true);
  107.     }
  108.   }
  109. }
  110.  
  111. //---------------------------------------------------------------------------
  112. // Tratamiento de Mensajes
  113. LRESULT __stdcall TLVCopy::DefListViewProc(HWND hWnd, UINT Msg, WPARAM WParam, LPARAM LParam)
  114. {
  115.   TLVCopy* pLVCopy = (TLVCopy*)GetWindowLongPtr(hWnd, GWL_USERDATA);
  116.   if(pLVCopy)
  117.     return pLVCopy->ListViewProc(hWnd, Msg, WParam, LParam);
  118.   else return DefWindowProc(hWnd, Msg, WParam, LParam);
  119. }
  120.  
  121. LRESULT __stdcall TLVCopy::ListViewProc(HWND hWnd, UINT Msg, WPARAM WParam, LPARAM LParam)
  122. {
  123.   if(Msg == WM_CONTEXTMENU){
  124.     POINT ScrPoint;
  125.     GetCursorPos(&ScrPoint);
  126.     Point = ScrPoint;
  127.     ScreenToClient(hWnd, &Point);
  128.     int Item, Si;
  129.     Item = GetItemAndSubItem(hListView, Point.x, Point.y, &Si);
  130.     if(hMenu && Item >= 0 && Si >=0){
  131.       TrackPopupMenuEx(hMenu, 0, ScrPoint.x, ScrPoint.y, hListView, 0);
  132.       return DefWindowProc(hWnd, Msg, WParam, LParam);
  133.     }
  134.   }
  135.   else if(Msg == WM_COMMAND){
  136.     if(WParam == (UINT)MenuIndex)
  137.       Copy();   // Copio el campo al portapapeles
  138.     else if(WParam & 0x0000FFFF){
  139.       // Si el menú es externo se rebota el mensaje para que la ventana de tratamiento del menú
  140.       // pueda tratar el comando
  141.       PostMessage(Window, WM_COMMAND, WParam, 0);
  142.     }
  143.   }
  144.   return CallWindowProc(OldListViewProc, hWnd, Msg, WParam, LParam);
  145. }
  146.  
  147. // Cuando ya se dispone de un menú, se puede usar pasando su Handle, el Index para
  148. // activar el Copy y la ventana de tratamiento de mensajes del menú existente
  149. void TLVCopy::SetHandle(HWND HListView, char *Text, HMENU hmenu, int menuIndex, HWND hWnd)
  150. {
  151.   if(hListView || HListView == INVALID_HANDLE_VALUE || !HListView)
  152.   if(hListView){
  153.     SetWindowLong(hListView, GWL_USERDATA, 0);
  154.     SetWindowLong(hListView, GWL_WNDPROC, (LONG)OldListViewProc);
  155.     hListView = 0;
  156.     if(DeleteMenu) DestroyMenu(hMenu);
  157.   }
  158.   if(HListView != INVALID_HANDLE_VALUE && HListView){
  159.     hListView = HListView;
  160.     SetWindowLongPtr(hListView, GWL_USERDATA, (LONG)this);
  161.     OldListViewProc = (PLRESULT)SetWindowLongPtr(hListView, GWL_WNDPROC, (LONG)TLVCopy::DefListViewProc);
  162.     if(hmenu != INVALID_HANDLE_VALUE){
  163.       if(hmenu){
  164.         hMenu = hmenu;
  165.         Window = hWnd;
  166.         MenuIndex = menuIndex;
  167.         DeleteMenu = false;
  168.         if(Text)
  169.           InsertMenuA(hMenu, 0, MF_POPUP | MF_BYPOSITION, MenuIndex, Text);
  170.       }
  171.       else{
  172.         hMenu = CreatePopupMenu();
  173.         MenuIndex = 0;
  174.         DeleteMenu = true;
  175.         if(Text)
  176.           InsertMenuA(hMenu, 0, MF_POPUP, MenuIndex, Text);
  177.         else
  178.           InsertMenuA(hMenu, 0, MF_POPUP, MenuIndex, "Copiar Campo");
  179.       }
  180.     }
  181.   }
  182. }
  183.  
  184.  
  185. TLVCopy::~TLVCopy()
  186. {
  187.   hMenu = 0;
  188.   SetHandle(0);
  189. }

Un ejemplo de uso:


cpp
  1. //---------------------------------------------------------------------------
  2.  
  3. #include <vcl.h>
  4. #pragma hdrstop
  5.  
  6. #include "Unit1.h"
  7.  
  8.  
  9. //---------------------------------------------------------------------------
  10. #pragma package(smart_init)
  11. #pragma resource "*.dfm"
  12. TForm1 *Form1;
  13.  
  14.  
  15. //---------------------------------------------------------------------------
  16. __fastcall TForm1::TForm1(TComponent* Owner)
  17. : TForm(Owner)
  18. {
  19. LVCopy.SetHandle(ListView->Handle, "Copia esto");
  20. }
  21. //---------------------------------------------------------------------------

Como podéis ver, en este caso, asignamos un texto a nuestro menú.

 

 

Saludos.


  • 1

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14460 posts
  • LocationMéxico

Posted 13 July 2018 - 11:32 AM

Buenísimo, gracias amigo (y)

 

Saludos


  • 0

#4 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 16 August 2018 - 01:49 PM

He actualizado el código para mejorar el comportamiento cuando se usa un menú ya existente.

 

 

Saludos.


  • 1





Also tagged with one or more of these keywords: TListView, Copy

IP.Board spam blocked by CleanTalk.