Link to home
Start Free TrialLog in
Avatar of cc_2000_sg
cc_2000_sg

asked on

hi, help me!

hi all,

i have 2 questions need your help.

Firstly, I have one button, i want to left click the button to show the popupmenu. but what i can do
now is only right click the button to show it. any good suggestion to me?

secondly, now i have mainly finished my application, and then i find that i have to add a new frame
to my main application, for example, i click the button in the new frame, then it disappeared, and the
main one is shown.
how can i do it?



thanks a lot

cc
Avatar of d32coder
d32coder

you can use the Button.OnClick event to open the popmenu by using the popmenu1.popup method.

positioning the menu in the right place is not automatic but you can specify the position in pixels in the parameters of the popup command.

Let me know if you need more details.

Don
Avatar of cc_2000_sg

ASKER

hi,

thanks,

now i can solve the first question.

can you help me solve the second one?

i want some detailed code.


thanks a lot

cc
hello cc_2000_sg, I'm not sure I understand your second question? ?, If you add another frame and it has a button, and you want the new frame to disapear (hide) when you click the button? then in the Button1Click event you might use this code

FrameNew.Hide;
Frame1.Show;

You may not need the Frame1.Show; if thst frame is visible. Is this what you are asking about?
Sorry cc, I know nothing about frames...

Don
ASKER CERTIFIED SOLUTION
Avatar of DelphiArchitect
DelphiArchitect

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi,
About your first question:
procedure TForm1.Button1MouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 TButton(Sender).PopupMenu.Popup(Mouse.CursorPos.X,Mouse.CursorPos.Y);
end;

Regards, Geo
Geobut,

Components should never be directly type cast, such as:

  TButton(Sender)

What would happen if this event were assigned to another components (maybe a TAction) or was called directly like:

  Button1Click(nil);

Always use the is & as operators instead:

  (Sender as TButton)).

At least this way if Sender is not a TButton you'll get an exception thrown.  By directly type casting it you could end up with all types of mysterious errors such as memory corruption, which is extremely difficult to track down.  The only time you should use a direct type cast is if you need to convert a pointer into an object, because you can't use is & as on pointers.  In such a case a statement such as the following is preferable:

  TObject(ButtonPointer) as TButton

Also, it is probably not desirable to use the TButton's PopupMenu property.  That property is used to assign a menu to be displayed when the component is right clicked (its context menu).  Good UI design would have the menu appear when you (left) click the button, but not when you right click it.  For example, if the button is on a TToolBar the ToolBar may have a context menu that you always want displayed.  By using the TButton's PopupMenu the ToolBar menu would not be displayed if you just happened to right click on that button, which is inconsistent UI behavior.

James Higgins
Delphi Architect
DelphiArchitect,

Do you recommend to 'hard code' ButtonX name in the event? I don't think that it's good programming practice. What would happen if the name of the button were changed later?

I also think that your way of showing the popup menu (its coordinates) doesn't comply to "Good UI design" you mentioned above.

Both TButton(Sender).property and (Sender as TButton).property would raise AV if the Sender were nil. The solution is to check if the Sender is TButton first.

My point of view is that there is no perfect code that fits in all possible situations. And there is always more than one solution to any problem. Everyone's piece of code could be made better or different. Here we have specific questions and our aim is to find out specific solutions not to write books. If we spoke in general it would lead us to an endless discusions.

Regards, Geo
if Sender is TButton then
   TButton(Sender).Caption := 'OK'
else
   ShowMessage('Sender was not a button');
geobul,

Actually, there is nothing wrong with "hard coding" the name of ButtonX in the event.  Components should very rarely ever change name, exactly because you have to hard code their names in many places.  Besides, if you do have to rename the control for some reason then the compiler will generate an error reminding you to rename the control in your code.  That code was taken from an event where I have the menu "drop Down" relevant to a different control than the button.  Which is why the control name is, and must be, hard coded.

I don't understnad your 2nd comment.  Why doesn't that way of showing the popup comply with good UI design?  It shows up the same to the user regardless of if you hard code the name of the component or not.

Actually, "Sender is TButton" will also raise an AV.  You must check if Sender is nil before doing anything with it to be completely safe.  But at least "(Sender as TButton)" would throw an exception if Sender was not a TButton, where "TButton(Sender)" would just cause ambiguous errors.

Obviously there are many ways to sovle a problem, and some are better than others.    I felt that it was important to point out the very serious problems of directly type casting objects.  This is the reason that "is" and "as" exist in Delphi.  Not all programmers, espicially those fairly new to Delphi, understand this.  So I took the oppertunity to clarify the issue.  Espicially since I do not know cc_2000_sq's experience level.  This is his question and I wanted to give him the best, and most thurough, answer possible.  If you took personal offense at anything I said you have my apology.

Regards,
James Higgins
Delphi Architect
It's common Windows practice to show a popup menu at mouse coordinates when a mouse click occurs. We are talking about mouse right-click all the time.

>Actually, "Sender is TButton" will also raise an AV

Let me disagree with you.

Regards, Geo
I guess the "Sender is TButton" argument boils down to coding style.  I never call a procedure with nil, and any component calling the procedure will not use nil.  Am I wrong?

Don
Geobul,

We are not talking about right click / context menus!  If the menu appears by pressing a button, it is a drop-down menu.  Windows UI standards are that the menu will drop down below the control (or related control) that summoned it.  When you press the "down" button on a TComboBox the menu doesn't appear at your mouse coordinates, it appears under the editbox.  Some thing applies here.

As far as the type casting issue, I am NOT concerned about the NIL case.  You are correct, both methods would cause an AV.  The best code would actually be:

begin
  if (Sender <> nil) and (Sender is TButton)
    then (Sender as TButton).whatever
end;

The problem, which I hope you can see and agree upon, is that forcibly type casting a component to TButton may cause corruption.  If at some point a TMenuItem gets its OnClick event assigned to the same event the TButton(Sender) will still not cause an error!  What it could do is cause serious problems however.  Lets say you did :

  TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked;

If this code was called by any object other than a TMenuItem it would trash that control's memory without any warning or error messages!  This is why type casting objects is an extremely bad practice and should never be done.  If there is a problem you WANT an exception to occur so that you can fix the problem.  What you don't want is for things to appear to work yet cause mysterious problems (possibly several minutes after you did this action), which is what memory corruption does to you.

Anyway, I am going to drop this point.  Hopefully I have made myself clear and you can understand my point behind this.  If you don't believe me then go check this out with Borland as I'm certain they will say the exact same thing (maybe they have this published as part of their code style guide or something).


d32coder,

You are correct, and if you are the only person that will ever touch that code then don't worry about it.  My code must be maintainable by others and I won't make assumptions on how they will program.  Better be safe than sorry in my book.  So maybe you don't need to check for nil, but I do at least hope that you are using as instead of direct type casting.


James Higgins
Delphi Architect
Hi Don, exactly, you said it in a few words and I couldn't. There are functions and procedures for reusable code and event handlers should be used to handle events. (wonderful sentence ;-)

Hi James, I see very well what you mean. And in general I agree with you. But I placed my code in Button.MouseUp event handler, not Click as you did. On the other hand the questioner said that he/she was able to popup the desired menu using right-click, i.e. associated with the button popup menu. If it were a toolbar, I would use TToolButton. It already has dropdown menu and popup menu, as well.

Hi cc, I'm very sorry that we used your question a little bit outside the issue.

Regards, Geo
thanks all,

you all give me a lot of idea about Delphi


:)

cc
cc,

Did you maybe forget to close out this question and award the points to someone?  Not necessarily saying that I in particular deserve (at least all) of the point, but you should award them to someone at least.

James Higgins
Delphi Architect
cc_2000_sg:

You have many open questions:

https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20244798
https://www.experts-exchange.com/jsp/qShow.jsp?ta=java&qid=20207015
https://www.experts-exchange.com/jsp/qShow.jsp?ta=visualbasic&qid=20265037
https://www.experts-exchange.com/jsp/qShow.jsp?ta=xml&qid=20168208
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20245899
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20253932
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20257549
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20258338
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20258362
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20263682
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=20263684
https://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=20246240

To assist you in your cleanup, I'm providing the following guidelines:

1.  Stay active in your questions and provide feedback whenever possible. Likewise, when feedback has not been provided by the experts, commenting again makes them receive an email notification, and they may provide you with further information. Experts have no other method of searching for questions in which they have commented, except manually.

2.  Award points by hitting the Accept Comment As Answer button located above and to the left of that expert's comment.

3.  When grading, be sure to read:
https://www.experts-exchange.com/jsp/cmtyQuestAnswer.jsp#3
to ensure that you understand the grading system here at EE. If you grade less than an A, you must explain why.

4.  Questions that were not helpful to you should be PAQ'd (stored in the database for their valuable content?even if not valuable to you) or deleted. To PAQ or delete a question, you must first post your intent in that question to make the experts aware. Then, if no experts object after three full days, you can post a zero-point question at community support to request deletion or PAQ. Please include the link(s) to the question(s).
CS:  https://www.experts-exchange.com/jsp/qList.jsp?ta=commspt
At that point, a moderator can refund your points and PAQ or delete the question for you. The delete button does not work.

5.  If you fail to respond to this cleanup request, I must report you to the Community Support Administrator for further action.

Our intent is to get the questions cleaned up, and not to embarrass or shame anyone. If you have any questions or need further assistance at all, feel free to ask me in this question or post a zero-point question at CS. We are very happy to help you in this task!


thanks!
amp
community support moderator