Perl win32::GUI progressbar - perl

Progress bar is not following the script. I want to display progressbar as the script executes. when it done it should stop. currently it is displying full process then going for printing output.
Please find my code below:
$Progress_bars = $main->AddProgressBar(
-pos => [10,840],
-background => [0,255,85],
-smooth => 1,
-size => [470,20],
);
my $intended_max = 100;
my $x = 11;
my $y = int($intended_max/$x);
$Progress_bars->SetRange(0,$x*$y);
for (1 .. $x) {
Win32::GUI::DoEvents();
$Progress_bars->SetStep($y);
$Progress_bars->StepIt();
Win32::Sleep(50);
}
$output = $telnet->print('ls');
print $output;

You're code is increasing the value by the progress value rather than setting it directly.
Try calling the SetPos methods instead of SetStep and StepIt.
(Note that I don't use Win32::GUI, so I'm guessing the method name based on MSDN.)

Related

How can I detect window resize event using Win32::GUI and WM_DISPLAYCHANGE?

I am struggling to make a simple receive WM_DISPLAYCHANGE informing my Win32::GUI app that the Windows Screen Resolution has changed, since the results for this question here is "0" accordingly informed by the search engine.
Could you provide a simple working example of a simple Win32::GUI program that detects a WM_DISPLAYCHANGE message and prints some info about that change in resolution?
From user "beech" at PerlMonks: http://perlmonks.org/index.pl?node_id=1171819
Try using the Hook method:
something like
$main->Hook( WM_DISPLAYCHANGE(), \&onDisplayChange );
sub onDisplayChange {
my( $object, $wParam, $lParam, $type, $msgcode) = #_;
print "Click handler called!\n";
}
Give a name to your window. Let's call it Main.
$main = Win32::GUI::Window->new(
-name => 'Main',
-width => 100,
-height => 100,
);
Now, define an event handler for the window. It should be of below pattern:
<window name>_<event name>
For example, for Resize event the event handler should be Main_Resize.
sub Main_Resize {
my $mw = $main->ScaleWidth();
my $mh = $main->ScaleHeight();
my $lw = $label->Width();
my $lh = $label->Height();
#print the height/width or whatever you want
}
I would suggest going through Win32::GUI::Tutorial.

VMware vCLI Perl "who done it" script

I've been trying to do this for a while and I just can't seem to understand the vCLI SDK. I believe the MO that I want to use is
ServiceContent->Task Manager, then print out the recent task. Here is my subroutine for doing it:
sub TaskManager {
my $begin;
my $mor = Vim::get_service_content()->taskManager;
my $taskmanager_view = Vim::get_view(mo_ref => $mor);
my $my_filterSpec = TaskFilterSpec->new();
my $eventArray = $taskmanager_view->CreateCollectorForTasks(filter => $my_filterSpec);
foreach (#$eventArray) {
# my $collector_view = Vim::get_view(mo_ref => $eventArray);
print $_->recentTask . "\n";
}
}
When I run this I either get:
Not an ARRAY reference at ./TaskManager.pl line 43.
When I change this, I then get:
subroutine &ManagedObjectReference::recentTask called at ./TaskManager.pl line 45
Here's one of the DOCS I've been looking at
https://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.TaskManager.html
I also have some conversations happening here:
https://www.reddit.com/r/vmware/comments/4qfaql/help_with_vcli_perl_script/
EDIT: I changed my subroutine to the following:
sub TaskManager {
my $begin;
my $mor = Vim::get_service_content()->taskManager;
my $taskmanager_view = Vim::get_view(mo_ref => $mor);
my $my_filterSpec = TaskFilterSpec->new();
my $eventArray = $taskmanager_view->CreateCollectorForTasks(filter => $my_filterSpec);
foreach ($eventArray) {
my $newRecentTask = $taskmanager_view->description;
print $newRecentTask . "\n";
}
}
But the problem is that the print statement is returning a hash value, not something I can use. Any ideas how to get something readable?

Creating a clean and proper Perl TK checkbox

Is there a more efficient and less code way to do the below without making it too confusing? I want to make sure I track each value as I want to run seperate functions depending if $average_value was selected or possible all three options were selected. The program is a basic data analytical application to give you an idea.
EDIT:
Adding the following code, which makes it act like a boolean being that Perl does not use "TRUE" or "FALSE and instead uses ZERO or ONE values.
$differences = $tab1 -> Checkbutton(
-text => "Differences",
-font => \$fontdefault,
-variable => \$differences_value,
$totalcheck = $average_value+$duplicates_value+$differences_value;
The code above is using -variable. I suppose addin the above may provide more information as to whether this was efficient coding or not--or possibly the shortest best method. Perl gets very confusing after hundreds of lines and I am trying to figure out the best methods possible.
ORIGINAL:
if ($totalcheck <= 0 ) {
my $d = $mw->Dialog(
-title => "ERROR: Blank",
-bitmap => 'warning',
-text => "No selection made.",
);
$d->Show;
} else {
if ($average_value > 0) {
print "average\n"
}
if ($duplicates_value > 0){
print "duplicates\n"
}
if ($differences_value > 0){
print "differences\n"
}
}

Perl/Curses event handling and I/O

So, I just started trying to use the perl curses module for a project I'm working on. The documentation seems to be extremely lacking, what little I can find on cpan seems to be half-finished and assumes previous curses library experience, which I don't have. I have two issues I am trying to solve, my code so far:
#!/usr/bin/perl
use strict;
use Curses::UI;
use Term::ReadKey;
my ($cols, $rows, $wp, $hp) = GetTerminalSize();
my $cui = new Curses::UI( -color_support => 1);
sub eDialog {
my $return = $cui->dialog(
-message => "Are you sure?",
-title => "Really quit?",
-buttons => ['yes', 'no']
);
exit(0) if $return;
}
sub entryUpdate {
my $mainentry = shift;
if($mainEntry->get() =~ m/.*\n$/)
{
print STDERR $mainEntry->get();
}
}
$cui->set_binding( \&eDialog , "\cQ");
my $mainWin = $cui->add(
'viewWin', 'Window',
-border => 1,
-height => ($rows - 3),
-bfg => 'green'
);
my $mainView = $mainWin->add(
"viewWid", "TextViewer",
-wrapping => 1
);
my $entryWin = $cui->add(
'entryWin', 'Window',
-border => 1,
-y => ($rows - 3),
-height => 1,
-bfg => 1
);
my $mainEntry = $entryWin->add(
"entryWid", "TextEntry",
-onchange => \&entryUpdate()
);
$mainEntry->focus();
$cui->mainloop();
I managed to get the UI set up how I want it, but actually making it work is proving problematic.
1). I want to be able to, when text is typed into the $mainEntry widget, detect when enter/return is pressed, and execute a subroutine to do stuff with the text typed into the widget, then clear it out. (I tried accomplishing this with the entryUpdate subroutine, but that isn't working at all, no matter how I've tried to do it.)
2). I want to be able to periodically (Say, every 1 second or 500ms), execute another subroutine, and have the string it returns added to the $mainView widget.
Getting either or both of these to work has proven to be a huge issue thus far, I just dont know enough about how curses works and I haven't been able to find the information I need anywhere. Any help would be much appreciated.
1) You can simply bind the return key to a subrouting using set_binding:
use Curses qw(KEY_ENTER);
$mainEntry->set_binding(sub {
$mainView->text($mainView->text . $mainEntry->get . "\n");
$mainView->draw;
$mainEntry->text("");
}, KEY_ENTER);
2) It seems that there are timer methods (found them by grepping the Curses-UI source code), but they are not documented, which is probably an issue. Here's how it's used:
$cui->set_timer('timer_name', sub {
$mainView->text($mainView->text . scalar(localtime)."\n");
$mainView->draw;
}, 1);

How can i repeatedly prompt the user with Tkx?

Using Perl Tkx, I want to get some input from the user, close the window, and maybe do it again later. For user input, I'm just displaying some buttons, and the user gets to click on one of them. Here's what I have now:
sub prompt_user {
my $answer;
my $mw = Tkx::widget->new("."); ## the main window is unavailable the second time
$mw->g_wm_title("Window Title"); ## line 40
$mw->g_wm_minsize(300, 200);
my $label = $mw->new_label( -text => "Question to the user?");
$label->g_pack( -padx => 10, -pady => 10);
my $button1 = $mw->new_button(
-text => "Option One",
-command => sub { $answer = 0; $mw->g_destroy; },
);
$button1->g_pack( -padx => 10, -pady => 10);
my $button2 = $mw->new_button(
-text => "Option Two",
-command => sub { $answer = 1; $mw->g_destroy; },
);
$button2->g_pack( -padx => 10, -pady => 10);
Tkx::MainLoop(); ## This blocks until the main window is killed
return $answer;
}
So the user clicks on one of the buttons, the window closes, prompt_user() returns 0 or 1 (depending on which button the user clicked), and execution continues. Until I try to prompt the user again. Then I get an error:
can't invoke "wm" command: application has been destroyed at MyFile.pm line 40
I just want a way to put up a bunch of buttons, let the user click one, wait to see which one is clicked, and maybe do it again later. Is there a way I can wait for a response to the button click without destroying the main window? Maybe create a subwindow?
I'm new to using Tkx, and googling shows lots of simple examples like the above code (using MainLoop/g_destroy), but I couldn't find any examples of recreating windows. I did see stuff about a Dialog Box or Message Box, but those won't suit my needs. I want to put text on the buttons, and use an arbitrary number of buttons (so I don't want to be limited to yes/no/cancel, and only have 3 options).
Update
Here's what I was able to use
# hide the main window, since I'm not using it
my $mw = Tkx::widget->new(".");
$mw->g_wm_withdraw();
# function to prompt the user to answer a question
# displays an arbitrary number of answers, each on its own button
sub prompt {
my $prompt = shift;
my $list_of_answers = shift;
# Note: the window name doesn't matter, as long as it's './something'
my $answer = Tkx::tk___dialog( "./mywindowpath", # window name
"Prompt", # window title
$prompt, # text to display
undef, # tk bmp library icon
undef, # default button
#$list_of_answers); # list of strings to use as buttons
return $answer;
}
# use the button to ask a question
my $index = prompt("Who was the best captain?",
[ "Kirk", "Picard", "Cisco", "Janeway", "Archer" ] );
I'm not really familiar with Tkx but Tk doesn't really work well that way. In general Tk applications are asynchronous. You should re-write your application in term of callbacks (kind of like javascript).
Basically, this kind of logic:
sub do_something {
perform_some_action();
my $result = prompt_user();
perform_some_other_action($result);
}
should be re-written to something like:
sub do_something {
perform_some_action();
prompt_user(perform_some_other_action);
}
Your program should basically not have a main loop. Instead the call to Tkx::MainLoop at the end of your program becomes the main loop and you should do all processing by handling events.
Having said that, there are some mechanisms available that emulates blocking. Read the documantation for vwait. Though, I think even that requires a running Tkx::MainLoop so it does not necessarily avoid refactoring your whole program.
On the question of how to create and destroy windows there are two solutions:
Use the main window (.) but don't destroy it at the end. Instead hide it and destroy all its children. You can then later reuse . by unhiding it.
Hide . and don't use it. Instead create other windows (toplevels) and use them. Since toplevels are children of . they are safe to destroy without screwing up Tk.