Recent

Author Topic: [SOLVED] Time for another one [Programatically add main menu items]  (Read 3824 times)

Rayvenhaus

  • Jr. Member
  • **
  • Posts: 70
First I want to thank all of you for your help on this forum. Can't express how much it means to find a community that really helps new people.  Thanks!!!

Secondly, I'm at a bit of a quandary. I've figured out how to enable/disable controls at run time. What I need to do next is a little bit more complicated.

Say I have a mainmenu control on a form. This form displays log files (Thanks molly!!!). Creating the mainmenu items for explicit log files was easy but I have a set of log files that can exist but may not exist.

One of the software programs I am monitoring creates a log file for each IP Daemon that is started. This number of log files can range from none (Though usually there is a minimum of 1) to a bunch of files, call called this:  IP_#.LOG where # is the sequential number, for example: IP_1.LOG,IP_2.LOG,IP_3.LOG,IP_4.LOG,.....IP_x.LOG. Since there is a variable number of log files I can't create the mainmenu items to view these logs before run time.

I think that I can do a for loop and look for IP_x.LOG and create the mainmenu items at run time, but I'm a bit unsure of how to do that. The problem that's throwing me is that I don't know how many of these files may or may not exist.
« Last Edit: December 06, 2016, 07:01:54 pm by Rayvenhaus »

lainz

  • Hero Member
  • *****
  • Posts: 4460
    • https://lainz.github.io/
Re: Time for another one
« Reply #1 on: November 27, 2016, 11:21:25 pm »
You can search for files in a folder (If the log files are all in the same folder) and then create the menu entries.

*.log or IP_*.log is the pattern to search, the function is called FindAllFiles. http://wiki.freepascal.org/FindAllFiles

There is a component called TMRUMenuManager that handles MRU files in your application, you can use that to create the menu items, instead of creating your own code. The component is under lazarus/components/mrumenu.

Code: Pascal  [Select][+][-]
  1. MRUMenuManager1.Recent.Add('some.log');
  2. MRUMenuManager1.ShowRecentFiles;

Edit: Seems that there is other TMRUManager in RX package too, see what is best for you. In that case you use the RX one, use it like this:

Code: Pascal  [Select][+][-]
  1.   MRUManager1.Add('some.log', 0);
« Last Edit: November 27, 2016, 11:34:35 pm by lainz »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Time for another one
« Reply #2 on: November 28, 2016, 12:11:48 am »
The attached project shows code you can adapt for your use. As written it expects some IP_#.LOG files in the program directory.

Rayvenhaus

  • Jr. Member
  • **
  • Posts: 70
Re: Time for another one [Programatically add main menu items]
« Reply #3 on: December 02, 2016, 03:59:01 pm »
Thanks howardpc. I've tried to adapt your code to mine but I can not get it to add the menu items. Can you take, or anyone for that matter, the attached project and let me know where I am going wrong?

wyckermain is where I am trying to do this. When the form is created, I read in an INI file. When it determines that the Mailer section is "Active" (Line 289 of wyckermain) it enables the menu item on the wyckerviewer form. At line 300 I attempt to incorporate your code to create the menu items for the existing IP_#.LOG files, if any exist, which they do on my system. I added your procedure, AddLogFIlesToMenu, in the implementation section of wyckermain. The program builds fine, it compiles fine, but no sub menu items are created on the wyckerviewer form under the IP Session Log section of the Argus (And Clones) menu item.

Thanks in advance!

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Time for another one [Programatically add main menu items]
« Reply #4 on: December 02, 2016, 06:25:45 pm »
@Rayvenhaus:
I understand that your problem currently is integrating this into your project but, it is very hard to be able to check that for someone trying to help as it requires a shitload of dependencies/packages to be installed (some of which are not even available for certain platforms).

Please keep that in mind when publishing your project. Some of the used packages/controls play no part in your (initial) problem and thus are redundant (well, not for your project of course  :) ).

Stripping down your original project has another advantage in that it makes it easier for you to comprehend the issue you are facing. Sometimes this even results in yourself being able to locate the problem.

Just saying.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Time for another one [Programatically add main menu items]
« Reply #5 on: December 02, 2016, 06:59:11 pm »
As molly indicated, debugging a project with a raft of third party packages is not easy.
However, I think you need to do the following:

Remove the entire AddLogFilesToMenu(...) procedure you had added as a stand-alone procedure.

Add "uses LCLProc;" to the implementation section of Wykermain.pas.
At the bottom of your form class declaration add a private parameterless AddLogFilesToMenu procedure thus:

Code: Pascal  [Select][+][-]
  1.  Tfrm_wyckermain = class(TForm)
  2.     Button1: TButton;
  3.     ...
  4.     procedure Timer2Timer(Sender: TObject);
  5.   private
  6.     procedure AddLogFilesToMenu;
  7.   public
  8.     { public declarations }
  9.   end;
                     

Press Ctrl-Shift-C to generate an implementation skeleton and complete it thus:

Code: Pascal  [Select][+][-]
  1. procedure Tfrm_wyckermain.AddLogFilesToMenu;
  2. var
  3.   fileList: TStringList;
  4.   i: integer;
  5.   t: PtrInt;
  6.   miArray: array of TMenuItem;
  7.   fn: string;
  8.  
  9.   function ValidLogID(out LogID: PtrInt): boolean;
  10.   var
  11.     error: word;
  12.     pDot: integer;
  13.   begin
  14.     pDot:=Pos('.', fn);
  15.     Val(Copy(fn, 4, pDot-4), LogID, error);
  16.     Exit(error = 0);
  17.   end;
  18.  
  19. begin
  20.   fileList:=FindAllFiles(your_log_file_directory, 'IP_*.LOG', False);
  21.   try
  22.     if (fileList.Count > 0) then begin
  23.       SetLength(miArray, fileList.Count);
  24.       for i:=0 to Pred(fileList.Count) do begin
  25.         miArray[i]:=TMenuItem.Create(MainMenu1);
  26.         fn:=ExtractFileName(fileList[i]);
  27.         miArray[i].Caption:=fn;
  28.         if not ValidLogID(t) then
  29.           RaiseGDBException('Log file has invalid name');
  30.         miArray[i].Tag:=t;
  31.         miArray[i].OnClick:=@MenuItem10Click; // <-- or whichever menuitemClick procedure is appropriate
  32.       end;
  33.       MainMenu1.Items.Add(NewSubMenu('View LOGS', 0, 'MenuItem11', miArray));
  34.     end;
  35.   finally
  36.     fileList.Free;
  37.   end;
  38. end;

Then remove all the parameters from your existing line that calls AddLogFilesToMenu, around line 300.
« Last Edit: December 02, 2016, 11:33:35 pm by howardpc »

Rayvenhaus

  • Jr. Member
  • **
  • Posts: 70
Re: Time for another one [Programatically add main menu items]
« Reply #6 on: December 06, 2016, 07:01:25 pm »
That did it, thank you very much howardpc!!

 

TinyPortal © 2005-2018