Print ListBox Control Contents - vb.net

I have a listbox control (in a WinForms application) that lists a bunch of statistics about records selected from a database.
Is there an easy way using VB .NET to take the contents of this listbox and send it all to the printer, or at least have one of those standard windows print dialogs come up, prompting the user for which printer to send the listbox contents to? Doesn't have to be fancy or anything.
Thanks!

You can take a look here:
https://stackoverflow.com/questions/5776452/how-to-print-in-vb-net/5780300#5780300
The first answer has a solution for printing a panel in Winforms that should be applicable to your situation.
EDIT WITH UPDATE:
Take a look at this MSDN article:
http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.print.aspx
If you can't use the method shown in the other question, you can always handle the PrintPage event of the PrintDocument object. Particularly look at the pd_PrintPage sub in that example, as it is the sub that handles the PrintPage event. You should be able to modify that sub to use the contents of your ListBox. You will iterate through your ListBox and "draw" each string onto the ev.Graphics object. The only tricky part is deciding how much will fit on one page, but the example covers that also.

Related

MS Word RibbonX How can I dynamically populate a combobox when a dotm file opens?

I'm a little stumped here. I'm diving deeper into designing ribbons for MS Word 2010, and I came across something new: populating comboboxes on the fly. In the image below, you can see...
...that I'm a dude who likes music while he works, just like any other dude. Problem is my list of playlists changes from time to time, so I don't want to hard-code that list into my ribbon's combobox. I can easily hard-code it, but I want this thing to be dynamic. And so, in my ribbon code:
<comboBox id="cmbPLaylist" label="Playlist" getItemLabel="Document_Open">
<item id="none" label="None"/>
</comboBox>
I have left only one item, "none," which is fine if I want the music player to launch with no playlist loaded. But what if I want a playlist to automatically load?
First, from my Google and book research, I've determined that I need to have a getItemLabel callback to populate the control. Is this the right way to go? But how do I run that automatically when my Normal.dotm loads? I'm having problems running this thing in the Document_Open event, and I've been reading online that I'm not alone.
My problem is a bit threefold: first, I'm really new at using these predefined callbacks like getEnabled, getItemLabel, etc. The callback territory is a very new territory for me. Second, I've never used a combobox in a ribbon before. Three, I've never dynamically populated a combobox in a ribbon before. I might be trying to bite off more than I can chew at once, but can anyone point me in the right direction?
My code so far, inserted into my Normal.dotm Document_Open event, is such:
Private Sub Document_Open(control As IRibbonControl, ByRef label)
Dim ListOfPlaylists() As String
ListOfPlaylists = GetPlaylists()
ListOfPlaylists(UBound(ListOfPlaylists)) = "Random"
End Sub
After this, I'm stumped. As you can see, I'm not sure how to tell MS Word, "Hey, MS Word, insert this value into the combobox list!"
Maybe it's my newbness at this whole thing, but when I Google for an answer, I'm not seeing it in the code. So any help is appreciated. Thanks!
I actually did some fiddling and almost stumbled on the answer. I put this in my code and it seems to work just fine now:
Sub drpPlaylists_getItemCount(Control As IRibbonControl, ByRef drpPlaylists_itemCount)
drpPlaylists_itemCount = UBound(ReadDirectoryContents(MusicDirectory, "*.m3u"))
End Sub
I guess this gets launched every time the ribbon has to reload itself. But it's solved for now. Still have some things to study up on on when these callbacks get called, but I'll figure this out. Thanks for the help!

Transferring data between two forms?

Okay so I've been searching for a solution for a while but can't seem to find any answers tailored to what I need to do. Also this is my first post here so I'm sorry if I'm being to vague with what I need. Basically I'm creating a program that has a few text boxes on one form and I need to display the data in those text boxes into a list box on another form. There's a button at the bottom of the first form that allows me to switch to form 2 and also display the data in the list box. I can switch to form 2 but nothing shows up in the list box. I also have a few radio buttons and check boxes on form 1 that will affect which constant values will need to show up in form 2's list box as well. One other thing is that I can't just use a form load option for getting data in the list box, it has to happen with the button press because I will be switching between forms and from my understanding the form load option only works once when the form is loaded for the first time. Anyway here is part of my code for form 1 that shows the button click:
Dim strCustomer As String
Private Sub btnPlaceOrder_Click(sender As Object, e As EventArgs) Handles btnPlaceOrder.Click
strCustomer = txtCustomer.Text
frmInvoice.ShowDialog()
frmInvoice.lstCustomerOrder.Items.Add(Me.strCustomer)
End Sub
My first form is frmMain and my second form is frmInvoice. Can anyone please help me with what I need to do differently with this code and what exactly I need to have for my code for form 2 to make this work. Again I am somewhat new to this so I'm sorry if any of this seems vague or if I'm not quite posting this is the right way. Also I'm using VB.
The code you provided should work fine but you are modifying the ListBox after you show the invoice Form. Since you are using showDialog(), the code that follows this statement will only be executed once the dialog form is dealt with (for example if you close it). This means that if you click the button a 2nd time, the ListBox should contain one item. If you switch the two lines so it looks like this, it should do what you expect it to:
frmInvoice.lstCustomerOrder.Items.Add(Me.strCustomer)
frmInvoice.ShowDialog()

retrieving controls from database

I am creating an application which requires dynamically loaded controls (to be precise buttons). These buttons are exactly the same, therefore the problem is not creating controls programatically, but making them work somehow. Each button should open a form, the form is being based on some data from the button. I'd like to have all the buttons use one event handler and open forms accordingly to the data it contains. Is there any way to do so? I don't know the types of these forms yet, therefore I can't use pre-defined "select case" or anything that would limit possibilities.
Another problem is that I would like to have some of the forms (modules) being "installed" independently. Is there any way to make that possible? I believe that could be completed using dlls, but I'm not sure. Is there any information on that, I've been looking for that for a while, but found nothing.
Regarding your first problem: You can create buttons in code; the answers to the following question should be enough to get you started (it's C#, but the principle is the same):
How to add Buttons in WinForm in Runtime?
In a nutshell:
Read your button configuration data from the database (or configuration file or whatever),
add the buttons to your user interface (see above),
use AddHandler to add an event handler to each of the buttons. For example:
AddHandler myButton.Click, Sub(sender, e)
' Do something
End Sub
(Regarding your second question: 1. It is unclear to me what you are asking and 2. you shouldn't ask two questions in the same SO question. I suggest that you open a new SO question for that and try to explain your requirement more clearly.)
Maybe i have not understand well your answer... But for your buttons:
1) Create a custom control, inheriting the Button control, and add the properties used for the creation of your forms.
2) In the Sub referenced by your eventHandler, the first argument is the control (the button) who raises the event, so you can use it's own properties to create your forms...
Adding to Heinzi's post:
Keep a list of the button names you created for use with AddHandler().
This code isn't exactly on point but it shows how the AddHandler() can be used at runtime:
' hook TextChanged/CheckedChanged for dirty logic
Dim chk As CheckBox
Dim rdo As RadioButton
For Each c As Control In FormDataControls
If c.Name.StartsWith("chk") Then
chk = c
AddHandler chk.CheckedChanged, AddressOf SetDirty
ElseIf c.Name.StartsWith("rdo") Then
rdo = c
AddHandler rdo.CheckedChanged, AddressOf SetDirty
Else
AddHandler c.TextChanged, AddressOf SetDirty
End If
Next
FormDataControls is my list of controls to target. In my case I use the Tag property to designate data controls.

What happened to control arrays

Few years ago I used to program with Visual Basic 6, I was able to create objects with the same name, then differ them by the index.
for example, we can create TextBox1 and another TextBox1 but with a different index.
now this feature is not available anymore!
Currently, I'm using Visual Studio 2012.
Is there anyway to manipulate VS2012 to enable that feature again, or is there something similar to it, because it was really helpful.
The easier way to accomplish a similar thing today is to place all of these controls in a common parent control. This parent could be a groupbox, a panel, or even the form itself.
So if, say, all of the checkboxes on your form need to be indexed, with no exception, you don't have to do anything special. If just one checkbox is different, you need that checkbox to have a different parent control than your indexed checkboxes. In this case, you could layer a panel control under the checkbox group, or you can layer a panel control under the single checkbox that is different. Either will work.
Later on, you will still not be able to access these checkboxes by index, but you will be able to treat them as a collection. Here's how you can do that:
For Each box As CheckBox In Me.Controls.OfType(Of Checkbox)()
'Do something with each checkbox
Next
Or if you want to know which ones are checked:
Dim checkedBoxes As IEnumerable(Of Checkbox) = Me.Controls.OfType(Of Checkbox)().Where(Function(b) b.Checked)
If you really want an array of the checkboxes, you can use this technique to get one. Just put code like this in your form's load event:
Dim checkBoxes() CheckBox = Me.Controls.OfType(Of CheckBox)().OrderBy(Function(b) b.Name).ToArray()
It's horrible painful now.
MSDN covers this subject now: http://msdn.microsoft.com/en-us/library/aa289500%28v=vs.71%29.aspx
Long live VB6!

VBA Status Bar

I am working on a Word VBA macro app for 80 or so users. The office has high staff turnover, so training suffers, and so one of the self imposed requirements for this project is comprehensive, friendly documentation. However, to supplement this, and to save newbies having to open up a 100 page document when they want to try something new, I want a status bar on every userform (there are five) that provides contextual help. I find tooltips annoying.
I don't have a lot of experience, so I was wanting to
Essentially, I have a file containing every status string. (This is currently a text file, but I was wondering if I should use a spreadsheet or csv for ease of editing by other staff in future.) Every control has a MouseMove event which refers to a function: getStatus(cID) that opens the file, grabs the line and displays it in the status label. It also grabs a few parameters from the same line in the file, such as whether the label is clickable (to link to a page in the help file), and what colour the label should be.
So a few questions really:
Will the application be slow if a userform is constantly referring to a file? It feels fine to me, but I've been in it far too long, and I'm the only user accessing that file. There will be 80 constantly accessing it.
Is MouseMove over a control the best way? Should I instead use co-ordinates?
Most importantly (in terms of me having to do as little work as possible) is there some way to do this so that I do not have to have a MouseMove event on every single control? I have a good few hundred or so controls, each with their own identifier (well, not yet, but they will if this is the only way to do it). Maybe when the form loads I could load ALL the possible status lines so they're ready for whenever the control is moused over. But then, maybe the loading time is negligible?
Appreciate any ideas or thoughts - especially if VBA already has a whole range of functions to do this already and I'm just trying to reinvent the wheel. I can't use the application status bar, because the user rarely sees the application itself.
Thanks!
EDIT:
It is for both data entry, clicking around and a bit of document generation.
It is a controlled environment so macro security issues aren't a big concern for me - and if something goes wrong it's someone else's fault or problem :)
Is this data entry app or do they just click stuff? Because often the field with focus is different to the item the mouse is hovering over, this can cause a lot of confusion.
Constantly reading from a file is a huge waste of time and resources - it is much better to load them only once into an array or collection when the form is loaded.
On MouseMouse event is better than coordinates because you can move things around without worrying. It's a lot of code but you should be able to generate most of that if you have a list of control names because the code should be identical.
ie
Sub Control_MouseMove()
DisplayStatus(Control)
End sub
I would consider the StatusText property and ControlTipText property of controls for this kind of help.
StatusText
This example sets the status bar help text for the form field named "Age."
With ActiveDocument.FormFields("Age")
.OwnStatus = True
.StatusText = "Type your current age."
End With
ControlTipText
This can be assigned from the property sheet for the control.
Private Sub UserForm_Initialize()
MultiPage1.Page1.ControlTipText = "Here in page 1"
MultiPage1.Page2.ControlTipText = "Now in page 2"
CommandButton1.ControlTipText = "And now here's"
CommandButton2.ControlTipText = "a tip from"
CommandButton3.ControlTipText = "your controls!"
End Sub