Move FlowLayoutPanel Controls via DragDrop - drag-and-drop

I have a FlowPanelLayout that can contain several UserControls called DataGridViewFilterSortElement. These controls look kind of like buttons, but different. I want the user to be able to click one of the DataGridViewFilterSortElement controls and drag it to another position (index) in the FlowLayoutPanel.
Is there a way to see the control physically moving as the user drags it to another position? In other words, is there a way to take a "snap shot" of the control that is being dragged (instead of a shadowed box) which would show the actual control moving as the cursor moves? Also, as the control is being dragged I'd like to have the other controls position to shift automatically instead of waiting for the user to drop the drag to see the shifts.
For example, let's say the FlowPanelLayout contains 3 controls and the user wants to drag the first control to the third controls position. So the user clicks and holds the first DataGridViewFilterSortElement, then drags over the second control, which causes the second control to shift to position 1 of 3, then the user drags over the third control, which causes the third control to shift to position 2 of 3, then the user drops the control in position 3. Is this possible? The little code I do have is below.
Here is a short little video that shows what I want to do: http://www.youtube.com/watch?v=YhyTni6KH0Q
Private Sub lblDescription_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown, lblDescription.MouseDown
' if the user left clicks and holds the element begin a DragDrop action
If e.Button = Windows.Forms.MouseButtons.Left Then
Me.DoDragDrop(Me, DragDropEffects.Move)
End If
End Sub
Private Sub SortFlowLayoutPanel_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Me.DragOver
e.Effect = DragDropEffects.Move
End Sub
Private Sub SortFlowLayoutPanel_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles SortFlowLayoutPanel.DragDrop
If e.Data.GetData(GetType(DataGridViewFilterSortElement)) IsNot Nothing Then
'Current Position
Dim myIndex As Integer = Me.SortFlowLayoutPanel.Controls.GetChildIndex(CType(e.Data.GetData(GetType(DataGridViewFilterSortElement)), DataGridViewFilterSortElement))
'Dragged to control to location of next picturebox
Dim element As DataGridViewFilterSortElement = CType(e.Data.GetData(GetType(DataGridViewFilterSortElement)), DataGridViewFilterSortElement)
Me.SortFlowLayoutPanel.Controls.SetChildIndex(element, myIndex)
End If
End Sub
Private Sub SortFlowLayoutPanel_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles SortFlowLayoutPanel.DragOver
e.Effect = DragDropEffects.Move
End Sub

This page explains how to do what you want. I tried it, looks pretty good.
http://www.vbdotnetforums.com/gui/45818-flowlayoutpanel-repositioning-object.html

Related

MS Access POS (point of sale) application - Dynamically populate a form from a list

I need to create a small MS Access touchscreen POS (point of sale) application.
If someone has a rudimentary touchscreen MS Access template they can point me to, so that I can learn from it, that would help tremendously.
I have been able to find code for a touchscreen keyboard, which I will use.
The person using the interface needs to click on the name of a person as part of the POS process. The people change often, so I need to update the list often.
I am looking for a way to use VBA to create the onscreen buttons dynamically based on a list of people I update in a separate form.
The form will naturally be full-screen, and will never have more than 50 buttons on the screen representing the list of people. Only a few (less than 5) other controls will be present on this form, so the buttons representing the list of people needs to be constrained to an area on the form. The form must read the list of people, then create fixed sized, large square buttons automatically and be arranged alphabetically from left to right.
Thank you.
Something like this should work for you then. You'll need to make the max amount of buttons you will need on the form and space them and make an OnClick event for each like the one here for Command0. Then when the form is opened the array is initialized and all the buttons are captioned and made visible up to the amount of records in the table.
When each button is clicked it calls the HandleClick Sub to interact with the data as you need.
I made the recordset global so that it is only filled once and avoid weird data issues if the customers table is updated while this form is in use.
Dim Buttons(1 To 4) As Control
Dim rst As DAO.Recordset
Private Sub Command0_Click()
HandleClick (1) 'number that corresponds to this button in the array as
'initialized in the Form_Load sub, hard coded
End Sub
Private Sub Form_Load()
'initialize the buttons
Buttons(1) = Me.Command0
Buttons(2) = Me.Command1
Buttons(3) = Me.Command2
Buttons(4) = Me.Command3
Dim sql As String
sql = "SELECT * FROM tblCustomers"
Set rst = CurrentDb.OpenRecordset(sql)
FillButtons
End Sub
Sub FillButtons()
If (rst.EOF And rst.BOF) = False Then
rst.MoveFirst
Dim itr As Integer
Do
Buttons(itr).Caption = rst("CustomerName")
Buttons(itr).Visible = True
rst.MoveNext
Loop While rst.EOF = False
End If
End Sub
Sub HandleClick(CustomerNumber As Integer)
'Here is where you do what you intended with the button using
'customer number to know which record was clicked
End Sub
It's a messy approach but it should work.

VBA Excel: How can I make one form change the position of another form?

I have two forms, frmPE and frmCRE. They are modal.
frmCRE has a button "Edit PE" that will open formPE (instance of frmPE).
If I don't play with the positions, formPE opens centered on top of frmCRE.
I would like to position them side by side so I can see both at once.
When I open frmPE, I can still see frmCRE but not touch it. That's OK.
' This code is in cmdEditPE
Set formPE = New frmPE
Load formPE
If Not formPE.bInitialize(vbFalse) Then Err.Raise glHANDLED_ERROR
Me.Left = 100 ' move frmCRE to the left so I can see it
formPE.Left = Me.Left + Me.Width ' move frmPE to move to the right side of frmCRE (bad)
formPE.Show
I think the problem is that when formPE opens, it uses its default left setting. From within PE, I can see that me.Left = 0 even though it was set before the show.
Is there a way I can use the formPE.bInitialize routine to see that frmCRE is open and find out its LEFT and WIDTH so I can set formPE.Left correctly, or a way I can set it from frmCRE as I was trying to do above?
Thanks
Shari
Use the Activae event of frmPE to move itself, but only if frmCRE is visible.
In frmPE
Private Sub UserForm_Activate()
If frmCRE.Visible Then
Me.Left = frmCRE.Left + frmCRE.Width
End If
End Sub

Specific element on top oflist CellTable/ Pager

is it possible to have a specific element on top of the list?
backgoround:
I have an event app, where new events are constantly added. The events are orderd by date. If an event passes, it is still on top of the page. Now that some time passed, the first elements are all over, so the first paged doesn't display any necassery data anymore. To get to events which will happen, the user has to click on the pager button.
I want this events to be displayed on top, and if the user want's to see previous events, he has to click the back button of the pager.
What have I tried:
cellTable.setVisibleRange(overElements, (overElements + totalEementCount));
this mixes up the whole pager logic, and the user can't switch from pager to page anymore.
SingleSelectionModel<JSEvents> selectionModel = new SingleSelectionModel<JSEvents>();
...
selectionModel.setSelected(nextEvent, true);
this selects the right element, and moves the pager to it, but the other elements are still visible, so if I have a few "over" events and in the worst case, only have a single "comming" event in the table. Also it is the usability is bad, since the user has to look which event is next and doesn't have it on top of the page...
If you're using a ListDataProvider, you can add the new event to the front of the list. Everything depending on that dataprovider will be notified and should redraw.
If you're using a different kind of data provider, you may have to call CellTable.redraw yourself, but I think AbstractDataProvider takes care of that for you.
As a first investigative step, you might just try calling cellTable.redraw() after your new event has been logged to see if that gets you anywhere.
found a solution:
the celltable has a method setVisibleRange. This method is used in the examples when a pager involved:
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
end = end >= data.size() ? data.size() : end;
List<JSEvents> sub = data.subList(start, end);
updateRowData(start, sub);
the updateRowData tells the celltable, which data is displayed and on which position this data starts.
Now if we want to have a speciffic element on top of the page we can use the same function. This is how I end up using it:
int end = start + PAGESIZE;
end = (end >= data.size()) ? data.size() : end;
List<JSEvents> sub = data.subList(start, end);
dataProvider.updateRowData(start, sub);
cellTable.setVisibleRange(start, sub.size());

Accessing Event Procedures of Form Controls with VBA in Excel

Is there any way to define event procedures for form controls such as the case with ActiveX objects?
I have a GUI which currently adds/removes ActiveX command buttons by the user but ran into Error 91 when trying to add an item to a global collection with each button added. My best guess is because of this much hated phenomenon. With the current state of the project, my best option is to switch to using form control buttons if I am able to define their event procedures. If not, I may need to somehow save the global variables and read them back after manipulating ActiveX control objects.
If you just want to add buttons and capture clicks, you can assign a common macro to them, and switch what action is taken based on the name of the button (which you would set when you create it, and which can be accessed via Application.Caller in the called procedure)
Sub AddButtons()
With ActiveSheet.Buttons.Add(100, 100, 50, 50)
.Name = "button1"
.OnAction = "ClickHandler"
End With
With ActiveSheet.Buttons.Add(200, 100, 50, 50)
.Name = "button2"
.OnAction = "ClickHandler"
End With
End Sub
Sub ClickHandler()
Dim bName As String
bName = Application.Caller
Select Case bName
Case "button1": MsgBox "Clicked First button"
Case "button2": AnotherSub
End Select
End Sub

Obtaining multiple touch or "Down" events for musical instrument

I am trying to detect multiple taps on the screen basically to create piano like app using the B4A SoundPool control and panel.touch event to trigger sounds.
My problem is that once the screen (or one panel of many representing keyboard) is touched and held others don't register.
I guess I would need to use a multitouch library but I can't figure out how I would use it to just detect multiple panels being touched. I don't need motion detection.
Here is my current code. One sub for all panels using Sender.Tag as unique identifier.
Is one Sub my problem?
Sub pnl_Touch (Action As Int, X As Float, Y As Float)
If Action = Activity.ACTION_DOWN Then
Dim key As Panel
key = Sender
Dim note As Int
note = key.Tag
Dim PlayID As Int
PlayID = SP.Play(note,1,1,1,0,1)
End If
End Sub
Yes, Multi-Touch is the way forward. See Andrew Graham's multi-touch library. Here is a working example - Multi-Touch tutorial