|
I am working on a touchscreen jukebox program like some of the more modern ones you may have seen in bars or pool halls. It's quite generic right now but I have been playing around with the ListView control to display an accurate representation of the current playlist. I have gotten it so that the user can DragDrop items (music files) in (*not "into" from an outside source..yet) the playlist to alter the order of the songs, i.e. move track 1 to track 3, thus resulting in track 2 becoming track 1 and track 3 becoming track 2. You get the picture. Actually it's quite like the playlist ListView in Windows Media player right now. In any cause, when the user moves the media up and/or down the list I am drawing a line on the ListView Control between the items that the chosen media is to be moved and thus inserted. I am using Graphics and Graphics.DrawLine and it works fine. However, I have to ListView.Refresh() everytime the line changes otherwise a whole bunch of lines will just continue to be drawn on the playlist ListView. It is in Detail Mode Behavior btw. This is all dandy when I have just a few items in the playlist but when I get around 30 or so when I drag an item to be moved the ListView Refreshing causes the control to flicker. Nothing major but annoying and unprofessional. How do I get this to quit? The Media Player for Windows does not flicker. Also on a side note, when the playlist becomes too big for the ListView the scrollbars take effect however on mine I get a horizontal one as well and do not want it. Do I have to resize the ListView when it reaches a certain number of items to accomodate the width of the vertical scrollbar or is there a way to tell the ListView control not to display the horizontal scrollbar at all? Any help, suggestions, or comments would be greatly appreciated.
|
|
|
|
|
Hi guys
my question is simple : Is there a way to dock the main window of an application on top of the screen. When it's dock, any other window maximized (even outside our application) would not be OVER or UNDER our main window? (as the Windows taskbar?)
It would work if we could SET Screen.workingArea() but it is readonly... Any ideas would be welcome... thx
============= --> our main window
------------|
| --> any window
|
|
|
|
------------|
============= --> Windows's taskbar
|
|
|
|
|
So i've been battling this problem for too long now and i'm hoping someone can assit me with either the design aspect or the code aspect (or both, if i'm that lucky).
Here's what i'm trying to do:
- I have a small command line application that basically runs SQL queries and saves the results to .csv files (call this repmake.exe)
-I will have many many instances of repmake.exe all running different sql queries (pass it as parameters when executed)
- I want to write another application to monitor all these RepMaker.exe ones. Ideally, when I launch this Monitor.exe app, it will query all processes, return the ones that are repmake.exe (this part is easy), and .. the hard part.. Give me a one line status message that is set in each repmake.exe
for example.. each repmake.exe would set a variable...
strStatus = "Running report #:3333"
I would like to monitor app to show me all the strStatus' from each repmake that is running.
HOW DO I DO THIS????
I looked into Remoting, but this doesn't seem like a good solution, as the Monitor program won't always be running, just every now and then, and the repmakers will waste too many resources always looking for a client everytime they change their status variable...
any other server-client solution doesn't seem to fit... i need a solution where the Monitor app queries each repmaker.exe for a value....
I could use a database and have all repmakers update that, but I'd rather not..
Any suggestions??
I don't know if this is possible, and maybe someone knows, but I've heard of 'hooking into' other processes and acccessing stuff.. is this viable in this scenario? How do i do this and what would I have to set up on the repmaker's to make this easier?
Thanks again!!!
|
|
|
|
|
Well, instead of querying all these processes...
I've done something similar to this before, except I wasn't getting status messages from a bunch processes on a single machine running an app, rather I was getting statuses of a process running on many servers.
My solution was to setup a Service application on a central server that just listened on a certain port for status messages sent by the worker app's. This service created an internal table of all the servers and what was going on on each of them.
I wrote a second application that just contacted the same service, on a different port, and just asked for the entire table when it started, then at specified intervals, asked for the records that were updated since the last download time. This app then just displayed all the status messages. This way, you could still collect status messages, even if your display app wasn't running.
If you so desired, this same setup could also be used to implement a command channel, with the service managing deployments of commands sent back to the clients doing the work.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Thanks for the reply... This is actually a pretty good idea and will look into it. What did you use for the communication part? Remoting?
|
|
|
|
|
Actually, I used UDP sockets to send messages. In my case, there was no need to have an exact representation of what was going on, so using a connectionless protocol worked nicely.
Remoting will also work. You could probably even use a Web Service to report back to a central database.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
How can i distribute the dot net dll?
We used to distribute active x dll for VB6 VC. At the installation with
installer,
we always reigster the dlls with regsvr32. However for dot net dlls
this doesn't work. I have been going through the web and some told me to use
regasa.exe. some says don't need to register and just ask custoemrs to
provide dot dll files
when developping with vb.net or c#. what is the real solution for this
issue?
SK
|
|
|
|
|
The real solution is to have your customers download the .NET Framework and install it first. You may be able to supply (redistribute) that with your application, but you cannot build it into your installer.
My: Blog | Photos
"Man who stand on hill with mouth open will wait long time for roast duck to drop in." -- Confucious
|
|
|
|
|
Search the MSDN for "Bootstrapping" + "NET Framework". Microsoft has an executable project that you can download that allows you to redistribute and install the NET Framework as part of your installation package.
|
|
|
|
|
Interesting... Last time I looked they were saying no you cannot do this as we don't allow it. Guess they must have changed their mind....
My: Blog | Photos
"Man who stand on hill with mouth open will wait long time for roast duck to drop in." -- Confucious
|
|
|
|
|
|
I own a small-potatoes business developing software.
I am working on a new WinForms product and need flexible reports with a min. budget.
I chose Crystal Reports because it came with VS .NET ("free").
I never used the product before (questionable decision), but figured I could learn it.
Anyway, my original grandiose plan required that reports:
1) Display data output from a stored procedure
2) Have fields disappear or drop-out from the report based on user's security level
3) Have dynamically built selection fields based on home-grown ad-hoc tool.
It appears that #2 and #3 are impossible, or, maybe can only be accomplished if I use all formula fields, and create a report with 1 field, another with 2 fields, another with 3 fields… etc. Then however many fields I want in my report, I choose the appropriate fields count report? – YUK.
I cannot even get #1 working!!
* When I create the report, it appears I need an SQL command (or procedure) to generate fields.
* I drag these fields onto the report.
* The user builds a where clause via a tool I created, and an SP is run with appropriate results.
* I assign the results to the report like this:
rpt.Load()
rpt.SetDataSource(ds)
… OR …
rpt.Database.Tables.Item(0).SetDataSource(ds)
rptViewer.ReportSource = rpt
* The data show is always whatever was returned from the query at DESIGN tim. The dataset assigned at run tim is ignored
* I did see suggestions ion the web stating to “Uncheck Save Data With Report on the file menu”. I cannot find this option.
ANY HELP?
Thanks,
-Len Miller
"If I had eight hours to chop down a tree, I'd spend six sharpening my axe."
-Abraham Lincoln
|
|
|
|
|
I only use Store Procedure to Edit data in SQL Server.
You should use Commang SQL to Crystal Report, with Command:
Public Function LayDuLieuDT(ByVal strSQL As String, ByVal table_name As String) As DataTable
Try
Dim oAdater As SqlClient.SqlDataAdapter
Dim oTable As New DataTable
Dim ds As New DataSet
oAdater = New SqlClient.SqlDataAdapter(strSQL, strConn)
oAdater.Fill(ds, table_name)
oTable = ds.Tables(table_name)
Return oTable
Catch
End Try
End Function
|
|
|
|
|
Hi, Thanks for trying to answer my questions, but I am not sure what you are saying here.
First, I DO use a stored procedure, and I want the dataet to be used at run time. This is my problem.
Second, you provide a function that returns a datatable. That is not needed for what my questions / issues are.
I have the problem where I specify OLEDB connection and a query at design time to specify my available fields. I drag these fields onto my report and save. Then at run time, I use the Crystal Reports Engine to specify the dataset (from my stored procedure results). But, the data always appears to be the result of the query specified at design time.
I Searched the web, and saw instructions to uncheck "Save Report With Data". on the File menu. This does not exist. I suspect this suggestion only applies to the full product, and not the Visual Studeio .NET version.
I had other issues too (Like how to dynamically make fields disappear based on app security priveledges, and whether a report can be built from scratc at run time, and whether Windows Authentication can be used / specified at RUN time) but this was my main problem.
Thanks,
-Len
Thanks,
-Len Miller
"If I had eight hours to chop down a tree, I'd spend six sharpening my axe."
-Abraham Lincoln
|
|
|
|
|
I have declared the following variables in the form transoverride.vb
Dim Account_Name, PolicyNumber, TransCodeOrig, TransEffDate, Override_Action, Override_New_Renewal, Override_Transaction_Code, ModifiedDate, ModifiedUID, Plan_Year As String
Dim RowNum As Integer
The goal of this question is that I want to pass the above variables to a dialog form called edittransoverride.
Public Sub DoModify()
Dim dTable As DataTable = Me.DataGrid1.DataSource
Dim bm As BindingManagerBase = Me.DataGrid1.BindingContext(Me.DataGrid1.DataSource, Me.DataGrid1.DataMember)
Dim dRow As DataRow = CType(bm.Current, DataRowView).Row
Me.lbNumRec.Text = Me.DsTransOverride1.Tables(0).Rows.Count.ToString()
Dim cEditTransOverride As New EditTransOverride
cEditTransOverride.ShowDialog()
cEditTransOverride.Dispose()
Me.SqlDataAdapter1.Update(Me.DsTransOverride1)
Me.DsTransOverride1.Tables(0).Clear()
Me.SqlDataAdapter1.Fill(Me.DsTransOverride1)
Me.DataGrid1.Refresh()
End Sub
In the subroutine that belogs to transoverride.vb I assign them values before passing to the dialog form.
Private Sub highLightRow(ByVal sender As Object, ByVal e As MouseEventArgs)
Dim pt = New Point(e.X, e.Y)
Dim grd As DataGrid = CType(sender, DataGrid)
Dim hit As DataGrid.HitTestInfo = grd.HitTest(pt)
If hit.Type = grd.HitTestType.Cell Then
grd.CurrentCell = New DataGridCell(hit.Row, hit.Column)
RowNum = hit.Row
grd.Select(RowNum)
Account_Name = Convert.ToString(grd.Item(RowNum, 0))
PolicyNumber = Convert.ToString(grd.Item(RowNum, 1))
TransCodeOrig = Convert.ToString(grd.Item(RowNum, 2))
TransEffDate = Convert.ToString(grd.Item(RowNum, 3))
Override_Action = Convert.ToString(grd.Item(RowNum, 4))
Override_New_Renewal = Convert.ToString(grd.Item(RowNum, 5))
Override_Transaction_Code = Convert.ToString(grd.Item(RowNum, 6))
ModifiedUID = Convert.ToString(grd.Item(RowNum, 7))
ModifiedDate = Convert.ToString(grd.Item(RowNum, 8))
Plan_Year = Convert.ToString(grd.Item(RowNum, 9))
End If
End Sub
Now I must get these values in the load of the edittransoverride.vb dialog form.
Private Sub EditForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Save old values
oldPolicyNumber = PolicyNumber
oldTransCode = TransCodeOrig
oldTransEffDate = TransEffDate
' Verify for Null fields
FillTextBox(txtAccountName, Account_Name)
FillTextBox(txtPolicyNumber, PolicyNumber)
FillTextBox(txtUserId, ModifiedUID)
dteEffDt.Text = TransEffDate.ToShortDateString()
dteEffDt.Value = TransEffDate.ToShortDateString()
FillTextBox(txtDate, ModifiedDate)
FillComboBox(cmbOriginalTransCode, TransCodeOrig)
FillComboBox(cmbOverrideAction, Override_Action)
FillComboBox(cmbOverrideNR, Override_New_Renewal)
FillComboBox(cmbOverrideTransactionCode, Override_Transaction_Code)
txtPlanYear.Text = Plan_Year
Me.lbRecNum.Text = RowNum
End Sub
How do I go about defining these variables so I can use them in my Load routine of the Dialog form.?
|
|
|
|
|
You don't need to use the Form_Load event.
Instead, first create public properties in the dialog form for each variable you wish to input.
Then, to use the form, first create an instance of the form class, and set all the properties with the input values. Then show the form modally.
|
|
|
|
|
' Dim Account_Name, PolicyNumber, TransCodeOrig, TransEffDate, Override_Action, Override_New_Renewal, Override_Transaction_Code, ModifiedDate, ModifiedUID, Plan_Year As String
Properties like so?
Public Property Account_Name() As String
Get
Return Me.txtAccountName.Text
End Get
Set(ByVal Value As String)
Me.txtAccountName.Text = Value
End Set
End Property
Public Property PolicyNumber() As String
Get
Return Me.txtPolicyNumber.Text
End Get
Set(ByVal Value As String)
Me.txtPolicyNumber.Text = Value
End Set
End Property
Public Property TransCodeOrig() As String
Get
Return Me.cmbOriginalTransCode.Text
End Get
Set(ByVal Value As String)
Me.cmbOriginalTransCode.Text = Value
End Set
End Property
|
|
|
|
|
What I have done is I build one public function and instead of load I am using that function
' inside modal form
Public function LoadForm ( x as int,list of other parameters) as boolen
' do load stuff here
return true
''' if error comes then return false
end function
now calling from the main form is
Dim frm as new form1
if frm.loadForm(parameters)=true then
frm.showdialog
end if
|
|
|
|
|
I am not calling from a form the dialog() I am calling it from a modify click button event.
|
|
|
|
|
offcourse you have to call it from any button click or any other event but ultimately the solution is as I told you. and if there is not modal/dialog form then please put the proper subject when you are submitting the problem.
|
|
|
|
|
Hi I am Deepak. I want to know that how i can give the XP look to the VB.net controls without making a saperate control with GDI programming.
I have made some controls like XP control but when i change the Scheme Default XP to Classic from control panel my control does not change its apearance. And these control also reduces the performance of Application.
Please help me.
|
|
|
|
|
In the constructor of your main form add the following:
Application.EnableVisualStyles()
Then you have to set the FlatStyle of your controls to System.
|
|
|
|
|
Hi I am Deepak. I want to know that how i can give the XP look to the VB.net controls without making a saperate control with GDI programming.
I have made some controls like XP control but when i change the Scheme Default XP to Classic from control panel my control does not change its apearance. And these control also reduces the performance of Application.
Please help me.
|
|
|
|
|
Hello,
I'm tying to work with a dll written in C that control's my fingerprint reader, the problem is i can't convert image data to a valid image in vb
dot net. The function EndAcquireImage fills a byte array with image information, the function ATCopyImagePixels extracts the pixels from the EndAcquireImage image data. With the ATGetImageXYSizes you can get width/height.
I tried several ways no luck at all, can someone help me?
Greetz
Dave
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic.ControlChars
Imports System.IO
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Structure _tsAT_API_MSG
Dim uiMessageType As UInt16
Dim pMessageData As IntPtr
End Structure
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATInit", SetLastError:=True)> _
Public Shared Function ATInit() As Int16
End Function
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATOpenSensorA", SetLastError:=True)> _
Public Shared Function ATOpenSensor(ByVal pszStrSensorName As SByte, ByVal iOpenMode As Int16) As Int16
End Function
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATBeginAcquireImage", SetLastError:=True)> _
Public Shared Function ATBeginAcquireImage(ByVal RetProc As CallbackHandler, ByRef uiCallerDWord As IntPtr, ByVal uiOperationType As UInt16, ByRef pVerifyTemplate As IntPtr) As Int16
End Function
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATEndAcquireImage", SetLastError:=True)> _
Public Shared Function ATEndAcquireImage(ByVal pImageItem() As System.Byte) As Int16
End Function
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATReleaseMessage", SetLastError:=True)> _
Public Shared Sub ATReleaseMessage(ByRef APIMsgToRelease As _tsAT_API_MSG)
End Sub
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATGetImageBufferSize", SetLastError:=True)> _
Public Shared Function ATGetImageBufferSize() As Int32
End Function
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATGetImagePixelBufferSize", SetLastError:=True)> _
Public Shared Function ATGetImagePixelBufferSize(ByVal pImageItem() As System.Byte) As Int32
End Function
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATCopyImagePixels", SetLastError:=True)> _
Public Shared Function ATCopyImagePixels(ByVal pPixelBuffer() As System.Byte, ByVal pImageItem() As System.Byte) As Int16
End Function
<DllImport("ATSC63.dll", CallingConvention:=CallingConvention.Cdecl, _
CharSet:=CharSet.Auto, EntryPoint:="ATGetImageXYSizes", SetLastError:=True)> _
Public Shared Function ATGetImageXYSizes(ByVal pImageItem() As System.Byte, ByRef piImageHeight As Int32, ByRef piImageWidth As Int32) As Int16
End Function
Delegate Sub CallbackHandler(ByRef uiCallerDWord As IntPtr, ByRef tsAT_API_MSG As _tsAT_API_MSG)
Public ImageItem() As System.Byte
Public ImageBufferSize As Int32
Public PixelBuffer() As System.Byte
Public PixelBufferSize As Int32
Public PixelHeight As Int32
Public PixelWidth As Int32
Public Sub translateInfo(ByRef tsAT_API_MSG As _tsAT_API_MSG)
Dim msgnumber As Int16 = Int16.Parse(tsAT_API_MSG.uiMessageType.ToString)
Select Case msgnumber
Case 0 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_NEW_DISPLAY_IMAGE"
Case 1 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_FINGER_DETECTED"
Case 2 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_FINGER_REMOVED"
Case 3 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_DATABASE_CHANGE"
Case 4 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_PLACE_FINGER"
Case 5
txtInfo.Text = txtInfo.Text & CrLf & "AT_API_ACQUIRE_DATA_RDY"
process_AT_API_ACQUIRE_DATA_RDY()
Case 6 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_ENROLL_DATA_RDY"
Case 7 : txtInfo.Text = txtInfo.Text & CrLf & "API_VALIDATE_DATA_RDY"
Case 8 : txtInfo.Text = txtInfo.Text & CrLf & "API_VERIFY_DATA_RDY"
Case 9 : txtInfo.Text = txtInfo.Text & CrLf & "API_IDENTIFY_DATA_RDY"
Case 10 : txtInfo.Text = txtInfo.Text & CrLf & "API_VERIFY_DATA_RDY"
Case 11 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_NO_CORE"
Case 12 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_LIFT_AND_REPLACE"
Case 13 : txtInfo.Text = txtInfo.Text & CrLf & "T_API_TIMEOUT"
Case 14 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_LOST_SENSOR_FOCUS"
Case 15 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_FAKE_FINGER_DETECTED"
Case 16 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_RESERVED_1"
Case 17 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SWIPE_TOO_FAST"
Case 18 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SWIPE_TOO_SLOW"
Case 19 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SENSOR_SURFACE_DIRTY"
Case 20 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SLIDE_FINGER"
Case 21 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_RESLIDE_FINGER"
Case 22 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_NAV_DATA_RDY"
Case 23 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SWIPE_TOO_SHORT"
Case 24 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SWIPE_TOO_SKEWED"
Case 25 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SWIPE_TOO_FAR_LEFT"
Case 26 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SWIPE_TOO_FAR_RIGHT"
Case 27 : txtInfo.Text = txtInfo.Text & CrLf & "AT_API_SWIPE_TOO_LITTLE_PRESSURE"
Case Else : MessageBox.Show(msgnumber.ToString)
End Select
ATReleaseMessage(tsAT_API_MSG)
End Sub
Private Sub parseGinfo(ByVal strInfo As String, ByVal result As Int16)
txtGinfo.Text = txtGinfo.Text & CrLf & strInfo & result.ToString
End Sub
Private Sub Messagehandler(ByRef uiCallerDWord As IntPtr, ByRef tsAT_API_MSG As _tsAT_API_MSG)
translateInfo(tsAT_API_MSG)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim result As Int16
result = ATInit()
parseGinfo("init: ", result)
result = ATOpenSensor(SByte.Parse("0"), Int16.Parse("2"))
parseGinfo("opensensor: ", result)
result = ATBeginAcquireImage(AddressOf Messagehandler, IntPtr.Zero, UInt16.Parse("0"), IntPtr.Zero)
parseGinfo("BeginAcquireImage: ", result)
End Sub
Private Sub process_AT_API_ACQUIRE_DATA_RDY()
Dim result As Int16
ImageBufferSize = ATGetImageBufferSize()
ReDim ImageItem(ImageBufferSize)
result = ATEndAcquireImage(ImageItem)
parseGinfo("EndAcquireImage: ", result)
PixelBufferSize = ATGetImagePixelBufferSize(ImageItem)
ReDim PixelBuffer(PixelBufferSize)
result = ATCopyImagePixels(PixelBuffer, ImageItem)
parseGinfo("CopyImagePixels: ", result)
result = ATGetImageXYSizes(PixelBuffer, PixelHeight, PixelWidth)
parseGinfo("GetImageXYSizes: ", result)
MessageBox.Show(PixelHeight & " " & PixelWidth)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim ms As New MemoryStream(PixelBuffer)
pbPrint.Image = Image.FromStream(ms)
pbPrint.SizeMode = PictureBoxSizeMode.CenterImage
End Sub
End Class
|
|
|
|
|
You'll have to consult the documentation on that library. Without knowing anything about the pixel format (like bits per pixel, color depth, palette indexing, data format) it's try to send to you, you'll only get it to work by stumbling on it by complete accident. Not a very efficient method of writing code, is it?
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|