Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

ExtendedSelect confusion...

Posted on 1999-06-24
13
Medium Priority
?
194 Views
Last Modified: 2010-04-06
Hi, this is a related question to my last one regarding trying to implement a ctrl character sequence...it turned out that the ExtendedSelect property was messing me up...along with the KeyDown event.
  Anyway, I now want to implement a ctrl-c command recognizable to my Listbox, so that the user can hi-lite an item, hit ctrl-c and it will copy the item's text to the Windows clipboard - simple enough. But when I hit ctrl-c, it  automatically selects the first item it sees beginning with the letter 'c'. I have Multi-select to true and ExtendedSelect to true. So I turn Extendedselect to false...but then when I click on an item it won't select it - it'll hi-lite it while my mouse click is down, but when I let the mouse click go, it un-selects...weird.

Here's my code:

procedure TForm1.ListBox1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var i, count : integer;
    selected_text : string;
begin

  {* if they press ctrl-c, do a copy of selected items to the clipboard *}

  if ((Key = ord('c')) and (ssCTRL in Shift)) or
     ((Key = ord('C')) and (ssCTRL in Shift)) then
  begin
    Key:=0;
    selected_text:='';
    for i := 0 to Listbox1.items.count -1 do
    begin
       if Listbox1.selected[i] = true then
       begin
         selected_text:=selected_text + Listbox1.items[i];
       end;
    end;
    Clipboard.settextbuf(PChar(selected_text));
  end;
end;


Thanks
   Shawn Halfpenny
0
Comment
Question by:aztec
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 3
  • 2
13 Comments
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1384465
Try moving your code to the OnKeyDown event - thats where the extendedselect stuff will be eating the key...

Let me know how it goes.

Cheers,

Raymond.

0
 
LVL 17

Expert Comment

by:inthe
ID: 1384466
hi shawn,
i agree with raymond .
i just tried it and it works ctrl-c on key down event and keep ctrl-a on key up event and have Extended select and multiselect on true.
although after selecting the text and pressing ctrl-c the active line becomes the nearest line that starts with a "c" ,the text has been copied to the clipboard.
also save yourself a line of coding by this:
if ((Key in [Ord('c'),Ord('C')]) and (ssCTRL in Shift)) then ...

Regards Barry
 
0
 
LVL 12

Accepted Solution

by:
rwilson032697 earned 200 total points
ID: 1384467
And with that endorsement, here it is as an answer...

Try moving your code to the OnKeyDown event - thats where the extendedselect stuff will be eating the key...  

Cheers,

Raymond.

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:aztec
ID: 1384468
Thanks guys, but it's *still* jumping right to the nearest item starting with a 'c' (although it *is* correctly copying the proper selected text to the clipboard). Here's my full code for both events:

procedure TForm1.ListBox1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var i, count : integer;
begin

  {* if they press ENTER key, or CTRL-A, select ALL the fieldnames *}

  if ((Key = ord('a')) and (ssCTRL in Shift)) or
     ((Key = ord('A')) and (ssCTRL in Shift)) or (Key = VK_RETURN) then
  begin
    Key:=0;
    for i := 0 to Listbox1.items.count -1 do
       Listbox1.selected[i] := true;
  end;

  {* if they press DELETE key, delete the selected files *}

  if (Key = VK_DELETE) then
  begin
    Count := ListBox1.Items.Count-1;
    if ListBox1.SelCount > 0 then
       For i:= Count DOWNTO 0 do
           if ListBox1.Selected[i] then
              ListBox1.Items.delete(i);
  end;


  if ListBox1.items.count = 1 then
     GroupBox1.Caption := IntToStr(ListBox1.items.count)+ ' Body Field Specified'
  else GroupBox1.Caption := IntToStr(ListBox1.items.count)+ ' Body Fields Specified';

end;

procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var i : integer;
    selected_text : string;
begin

  {* if they press ctrl-c, do a copy of selected items to the clipboard *}

  if ((Key = ord('c')) and (ssCTRL in Shift)) or
     ((Key = ord('C')) and (ssCTRL in Shift)) then
  begin
    Key:=0;
    selected_text:='';
    for i := 0 to Listbox1.items.count -1 do
    begin
       if Listbox1.selected[i] = true then
       begin
         selected_text:=selected_text + Listbox1.items[i];
       end;
    end;
    Clipboard.settextbuf(PChar(selected_text));
  end;
end;


...I have both Multiselect and ExtendedSelect set to true in the Listbox. Hope you can help!

Cheers
   Shawn

0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1384469
aztec: I have copied your code and yes it dows jump. Some tracing through the VCL doesn't seem to shed a lot of light on it at the moment though...

Cheers,

Raymond.

0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1384470
aztec: I've been looking at this for a bit now... the behaviour appears to be lodged deeply into the VCL/windows. I thought I had a way by adding LBS_WANTKEYBOARDINPUT to the listbox's style and handling the WM_CHARTOITEM and WM_VKEYTOITEM messages but this didn't work either.

inthe: Any ideas?

Cheers,

Raymond.

0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1384471
aztec: OK, I have the answer - its more of a workaround, but it works:

Add a popupmenu to your form, set its autopopup property to false (this stops the popup appearing when you right click). Add two items Copy (Ctrl C shortcut) and Select all (Ctrl A shortcut).
Set the listbox Popupmenu property to this popup. Now when you do Ctrl-C and Ctrl-A the listbox doesn't even get the chars!

Here is the Copy click event, the select all one should be elementary!

procedure TForm1.Copy1Click(Sender: TObject);
var i : integer;
    selected_text : string;

begin
    selected_text:='';
    for i := 0 to Listbox1.items.count -1 do
    begin
       if Listbox1.selected[i] = true then
       begin
         selected_text:=selected_text + Listbox1.items[i];
       end;
    end;
    Clipboard.settextbuf(PChar(selected_text));
end;

If you have any further problems - just yell!

Cheers,

Raymond.

0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1384472
PS: I suggest the popup in case you don't waint a main menu. If you have one then you could add the menu items to the main menu and forget about the popup.

0
 
LVL 17

Expert Comment

by:inthe
ID: 1384473
i tried several ways and coulnt get it to work correctly
the only idea i havnt tried is a small keyboard hook which i think would work.
with it ,it would sit in the background and when the keystroke of ctrl - c came along it could swallow the keys and pass the code along so it would leave the text selected until you click somewhere else.the only trouble is ive done several keyboard hooks before but never got one to work with 2 keys only 1 otherwise i'd  post the source for ya to try...therte are several sample of hooks on dejanews etc if you want to look into it more.

0
 

Author Comment

by:aztec
ID: 1384474
Thanks for the suggestion Raymond, but it still doesn't work. I made a popupmenu with a copy event in it like you say, set the Listbox popupmenu to this ...but when I select an item in the listbox and hit ctrl-c, it still just jumps to the first item starting with the letter 'c'...and also this time it doesn't even copy the items text to the clipboard...I stepped thru it - it's not even getting to the Copy1Click event when you press ctrl-c.
 

Thanks for your persistence on this...
Shawn
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1384475
aztec: Did you set the shortcut property of the popupmenu copy item to 'CTRL-C'? This worked just fine on my machine at work. I can post the code and DFM if you like (its pretty small).

The main reason this works is that the shortcut of the popup menu intercepts and processes the key before the listbox ever sees it.

Cheers,

Raymond.

0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1384476
axtec: Here is the full source for the app that works: (I forgot about the changed keydown function...)

Cheers,

Raymond.


program ClipboardProject;

uses
  Forms,
  Unit7 in 'Unit7.pas' {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


unit Unit7;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, unit8, Menus;

type
  TForm1 = class(TForm)
    ListBox1: TMyListBox;
    GroupBox1: TGroupBox;
    Edit1: TEdit;
    PopupMenu1: TPopupMenu;
    Copy1: TMenuItem;
    procedure ListBox1KeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure ListBox1KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Copy1Click(Sender: TObject);
  private

    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  clipbrd;

{$R *.DFM}

procedure TForm1.ListBox1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var i, count : integer;
begin
  {* if they press ENTER key, or CTRL-A, select ALL the fieldnames *}

  if ((Key = ord('a')) and (ssCTRL in Shift)) or
     ((Key = ord('A')) and (ssCTRL in Shift)) or (Key = VK_RETURN) then
  begin
    Key:=0;
    for i := 0 to Listbox1.items.count -1 do
       Listbox1.selected[i] := true;
  end;

  if ((Key = ord('c')) and (ssCTRL in Shift)) or
     ((Key = ord('C')) and (ssCTRL in Shift)) then
  begin
    Key:=0;
  end;
 
  {* if they press DELETE key, delete the selected files *}

  if (Key = VK_DELETE) then
  begin
    Count := ListBox1.Items.Count-1;
    if ListBox1.SelCount > 0 then
       For i:= Count DOWNTO 0 do
           if ListBox1.Selected[i] then
              ListBox1.Items.delete(i);
  end;


  if ListBox1.items.count = 1 then
     GroupBox1.Caption := IntToStr(ListBox1.items.count)+ ' Body Field Specified'
  else GroupBox1.Caption := IntToStr(ListBox1.items.count)+ ' Body Fields Specified';

end;

procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var i : integer;
    selected_text : string;
begin
if key=17 then
  key := 0;
end;

procedure TForm1.Copy1Click(Sender: TObject);
var i : integer;
    selected_text : string;

begin
    selected_text:='';
    for i := 0 to Listbox1.items.count -1 do
    begin
       if Listbox1.selected[i] = true then
       begin
         selected_text:=selected_text + Listbox1.items[i];
       end;
    end;
    Clipboard.settextbuf(PChar(selected_text));
end;

end.


object Form1: TForm1
  Left = 208
  Top = 189
  Width = 696
  Height = 480
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object ListBox1: TMylistBox
    Left = 264
    Top = 40
    Width = 185
    Height = 273
    ItemHeight = 13
    Items.Strings = (
      'one'
      'two'
      'c1'
      'three'
      'four'
      'five'
      'c2')
    MultiSelect = True
    PopupMenu = PopupMenu1
    TabOrder = 0
    OnKeyDown = ListBox1KeyDown
    OnKeyUp = ListBox1KeyUp
  end
  object GroupBox1: TGroupBox
    Left = 48
    Top = 32
    Width = 185
    Height = 105
    Caption = 'GroupBox1'
    TabOrder = 1
  end
  object Edit1: TEdit
    Left = 48
    Top = 192
    Width = 121
    Height = 21
    TabOrder = 2
    Text = 'Edit1'
  end
  object PopupMenu1: TPopupMenu
    AutoPopup = False
    Left = 328
    Top = 216
    object Copy1: TMenuItem
      Caption = 'Copy'
      ShortCut = 16451
      OnClick = Copy1Click
    end
  end
end
 
0
 

Author Comment

by:aztec
ID: 1384477
Ahhh yes, the shortcut property of the popupmenu copy! *That's* what I had forgot! It now works perfectly...thanks for all your help!

Cheers
   Shawn
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses

715 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question