How to Capture Function Keys in WebForms? - vb.net

I have very little experience of working with VB.NET Web Application.
I would like to know how to capture function keys (F1, F2... F12) in a "VB WebForms applications (Web Application)".
I have been searching on search engines and even here on stackoverflow but I kept getting results full of VB.NET Windows Forms which showed examples of _keydown event like
Private Sub xyz_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
I tried looking into my WebForm's different event like Form's event, TextBox's event etc. but couldn't find it anywhere. So I assume these are available for Windows Forms ONLY.
What I am trying to do is as follows -
In a TextBox when the user presses F1 key, open a new form which has a Gridview with some data
The user clicks on one row and the value(s) (one or more) of this row is captured in variable(s) and the form should close and control should come back to TextBox with the captured row data.
Also how can I setFocus on any particular row of TextBox?
Can someone please give me a small example of how this can be done.

You can't capture it on the server side, but maybe you could try this:
<script type="text/javascript">
$(document).on("keypress", function (e) {
var code = e.which;
if (code == 123) { // The F12 Key
$.ajax({
type: "POST",
url: "YourCallingPage.aspx/OpenForm",
contentType: "application/json; charset=utf-8",
dataType: "json"
});
}
});
</script>
Then in the codebehind of YourCallingPage.aspx(what ever page the textbox is on) add the following method(or whatever you name the method):
<System.Web.Services.WebMethod()> _
Public Shared Sub OpenForm()
HttpContext.Current.Response.Redirect("FormThatHasGrid.aspx")
End Sub
Now once you redirect back to YourCallingPage.aspx I guess you could append the selected grid value to the query string and populate the textbox like that, or some other method, but this is just a quick and dirty idea that may work for you.

Related

CefSharp SetZoomLevel not working

I am using in a WinForm an object of type:
CefSharp.WinForms.ChromiumWebBrowser
Everything is working fine but I am having an issue when I try to change the ZoomLevel with SetZoomLevel method:
If oBrowser.IsBrowserInitialized Then
oBrowser.SetZoomLevel(-2.0)
Dim frame As CefSharp.IFrame = oBrowser.GetMainFrame
Dim request As CefSharp.IRequest = frame.CreateRequest()
request.Url = url
request.Method = "POST"
request.InitializePostData()
Dim element = request.PostData.CreatePostDataElement()
element.Bytes = postDataBytes
request.PostData.AddElement(element)
request.Headers = headers
frame.LoadRequest(request)
End If
The first time I open the WinForm the Zoom level doesn't change, while it works correctly from the 2nd refresh.
Am I missing some initialization and/or method call... Or do I have to call this method in another position?
Note: the CEFSharp DLL version is 63.0.3.0.
The .NET Framework is 4.5.2
EDITED 01.06.2018: I've found a solution (see below) but now there's another problem: the zoom change is made when the browser is already visible, so it's not nice for the final user to see the page size changing during the form load.
Has anyone a suggestion to freeze the layout during zoom change? Please note that .SuspendLayout() and .ResumeLayout() are not working.
I've found a way to answer my own question. I post it here as it could be useful to other users.
You must add a LoadingStateChanged handler to the ChromiumWebBrowser object:
AddHandler oBrowser.LoadingStateChanged, AddressOf WebBrowserOnLoadingStateChanged
The method would be then something like:
Private Sub WebBrowserOnLoadingStateChanged(ByVal sender As Object, ByVal loadingStateChangedEventArgs As LoadingStateChangedEventArgs)
Dim oBrowser As WinForms.ChromiumWebBrowser = CType(sender, WinForms.ChromiumWebBrowser)
If Not oBrowser.IsLoading Then
oBrowser.SetZoomLevel(-2.0)
End If
End Sub
This solution works good in my environment but now there's another problem: the zoom change is made when the browser is already visible, so it's not nice for the final user to see the Zoom Level changing during the form load.

Looking for a specific tag

I had a previous question regarding a way to access a proxy card from within a web page when using Chrome. I'm now attempting to instead use a vb.Net application with an embedded CefSharp object. I have the code I need to access the proxy card (thanks to Smart Card API), but I need an easy way to indicate that this is even an option. My thought is to:
Put an otherwise empty element on the web page (such as <div id='smartcard' />)
Inside Visual Basic, monitor the contents of the page for this <div />
If the <div /> is found, make sure the card reader is detected. If so, add some text (and maybe an image) to its contents indicating the the card can be scanned
Once a card scan is detected, put the value from the card into a form element and POST it
It seems likely to me that I'm going to have to use some combination of JavaScript and vb.net code, but I'm so new to CefSharp that I really have no idea where to start.
Thanks in advance for all your help.
Not being a C# programmer, I looked at the information on the General Usage guide many times and still didn't really understand it. That said, I think I've been able to get this project off the ground. In addition to the CefSharp project, I'm also using the non-free Smart Card API from CardWerk.
Below is some snippets of what I did.
VB.Net
Imports CefSharp
Imports Subsembly ' For the SmartCard namespace
Class MainWindow
Private WithEvents CardManager As SmartCard.CardTerminalManager
Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
browser.Address = "https://jake-dev7.local/trainingmatrix/"
Debug.Print(SmartCard.SMARTCARDAPI.API_VERSION)
CardManager = SmartCard.CardTerminalManager.Singleton
CardManager.Startup(True)
End Sub
Private Sub browser_LoadingStateChanged(sender As Object, e As LoadingStateChangedEventArgs) Handles browser.LoadingStateChanged
Dim script As String
If Not e.IsLoading Then
If CardManager.SlotCount Then
script = "if ($('#proxcard').length) { proxcard_init() }"
browser.GetMainFrame().ExecuteJavaScriptAsync(script)
End If
End If
End Sub
Protected Sub InsertedEvent(ByVal aSender As Object, ByVal aEventArgs As SmartCard.CardTerminalEventArgs) Handles CardManager.CardInsertedEvent
Dim aCard As SmartCard.CardHandle
Dim nActivationResult As SmartCard.CardActivationResult
Dim iFacilityCode As Integer
Dim iCardID As Integer
' There's a bunch of code here taken from the sample code that came
' with the SmartCard API from CardWerk to pull the facility code and
' card id out of the prox card.
If iFacilityCode <> 0 And iCardID <> 0 Then
Dim script As String
script = "if ($('#proxcard').length) { proxcard_scan(" & iFacilityCode & ", " & iCardID & ") }"
browser.GetMainFrame().ExecuteJavaScriptAsync(script)
End If
End Sub
End Class
JavaScript
(This is in a .js file that is loaded by the web page. This page can also be loaded in Chrome, Firefox, IE, etc and these functions will never be run which keeps this utility usable for computers that don't have the custom .exe and card reader).
// These proxcard_* functions are called via our parent application
// (CefSharp object embeded in a vb.Net assembly)
function proxcard_init() {
$('#proxcard').html("<div class='or'>- OR -</div><div><img src='proxcard.jpg'><br>Scan your card</div>");
}
function proxcard_scan(facilityID, cardID) {
var vars = {
facilityID: facilityID,
cardID: cardID
};
if ($('form#adduser').length) {
// We're on the add user page. Check to see if this card matches somebody.
$.post('httprequest.php?type=get-emp-from-prox', vars, function(data) {
if (data && data.number) {
// Update UI and backend form fields. If everything validates, submit the form
} else {
// Clear UI and backend form fields that pertain to user ID
alert('Card not found');
}
}, 'json');
} else if ($('form#update').length) {
// Deal with the update form
}
}
In my actual code, I have multiple else if statements for dealing with different forms where I allow a card to be scanned. They are not included to keep this from getting out of hand :).
Please Note: This is not intended to be the entire project or all the code needed to process prox cards using CefSharp. My hope is that it will be enough to help somebody else.

How to clear Kendo grid rows without invoking databound method?

I have a grid with databound method which shows the message 'No Data Found for the search' in case no data gets retrieved after performing search. Now i have added a radio buttons which when clicked needs to clear the old data from the grid. The issue is i am using the code $(grid).data("kendoGrid").dataSource.data([]); which does clear the grid but it also shows 'No Data Found for the search' message. Since user didn't perform any search but only changed the radio button it doesn't seem right to display that message in the grid. So, i was wondering if there was a way to clear the grid without invoking the databound method.
Grid code that calls databound function:
#(Html.Kendo().Grid<SearchModel>()
.Events(events => events.DataBound("gridDataBound"))
Databound code:
function gridDataBound(e) {
var grid = e.sender;
var gridName = "#" + grid.table.context.id;
if (grid.dataSource.total() == 0) {
var colCount = grid.columns.length;
$(e.sender.wrapper)
.find('tbody')
.append('<tr class="kendo-data-row"><td colspan="' + colCount + '" class="no-data">No Records Meet Your Search Criteria.</td></tr>');
}
$(gridName).find(".k-pager-wrap").hide();
};
Thanks.
As far as i know there is no way of doing this without putting an e.preventDefault() in the dataBound function. What you can do is maybe make a boolean that your dataBound function uses to check whether it should display the message or not?

DataGridView editing cells on WinForms

I have a Windows Form VS2010 .NET 4 project with a standard DataGridView bound to a datasource on a form.
The grid has a text column that I want to be a point and edit at the character clicked to.
Like normal textbox/editors when you click on the character you want to adjust. If possible I would also like to use the UP/DOWN keys to move between rows but would like the cursor to move to the same character position obviously in the same column without selecting the entire text.
I have tried a few things:
DataGridView1.ClearSelection()
DataGridView1.BeginEdit(False)
The BeginEdit just puts the cursor at the end of the text, which means another click to point to the character position for editing.
I know a Commercial grid like DevExpress defaults to editing in which you can click to the correct character position with one click but obviously costs money.
I have tried in the DataGridView1_EditingControlShowing event
If TypeOf e.Control Is System.Windows.Forms.DataGridViewTextBoxEditingControl Then
Dim tb As TextBox = e.Control
tb.SelectionStart = 5
tb.SelectionLength = 5
End If
But this does nothing.
I am just trying to remove the two or three clicks to get to the character position that needs adjustment.
I haven't looked at a Custom DataColumn as yet.
Any suggestions would be greatly appreciated.
There is no good out of the box way of doing this. The closest there is is to set the EditMode of the grid to EditOnEnter but that means you only need two clicks, not three.
You will need to write your own column type.
Someone has done just that here.
I haven't checked if that example handles up and down - if it doesn't then you were on the right track with the SelectionStart and SelectionLength properties, just grab the caret position of the cell you are leaving and apply it to the new cell.
It turns out that setting these properties is a little bit more involved that I remembered (possibly because I was already using a MaskedTextBox custom column type last time I did this).
The code below (in c# but the principle holds for vb.Net and I can give the vb code if you can't convert it yourself) works happily - could be tidied up by putting it into a custom control but I'll leave that as an exercise :)
First I add a handler for the EditingControlShowing event:
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
DataGridViewTextBoxEditingControl t = e.Control as DataGridViewTextBoxEditingControl;
current_control = t;
t.Leave += new EventHandler(t_Leave);
}
In the method above current_control is a form level private variable. The event handler for t looks like this:
void t_Leave(object sender, EventArgs e)
{
cell_caret_pos = current_control.SelectionStart;
}
There again we have a class level private field - cell_caret_pos.
Then what I found was that to set SelectionStart and SelectionLength you need to work within the CellEnter event handler:
private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
dataGridView1.BeginEdit(false);
DataGridViewTextBoxEditingControl editControl =
(DataGridViewTextBoxEditingControl)dataGridView1.EditingControl;
if (cell_caret_pos != 0)
{
editControl.SelectionStart = cell_caret_pos;
editControl.SelectionLength = 0;
}
}

Dojo OnKeyPress Handler: TextBox value is blank

I have a Dojo form that does not contain a submit button. Instead, I added an onkeypress handler to calls a method when Enter is pressed. The problem I am having is that when I hit enter before blurring off the current field, the _process method thinks that field is empty.
Or in other words: type in field1. hit tab. type in field2. hit enter. field2 is blank unless i click off the field or shift-tab back.
Any ideas?
dojo.connect(dijit.byId("fkrform"),"onKeyPress",function(e) {
if (e.keyCode == dojo.keys.ENTER) {
_process();
}
and the method it calls:
function _process()
{
var field1 = dijit.byId("field1").value;
var field2 = dijit.byId("field2").value;
alert(username);
alert(password);
...do stuff...
}
The fields are of dojoType: dijit.form.TextBox, and the form is: dijit.form.Form
Use dijit.byId('field1').get('value') instead of directly try to access the property "value". In your example you saved the value in the variable field1 and field2 and in the alert you use the variable username and password could be the answer why you don't get anything. But you still should use the get method to get a property instead of directly access the property.
When you press "Enter" your form will submit. So you need to connect to the "onSubmit" event on the form, instead of onkeyPress or onKeyUp.
The first example i created prints the value of the input box on every key someone pressed in the console.
http://jsfiddle.net/a8FHg/
But what you really wanted was hooking into the submit. I modified the example. The new example connects to "onSubmit" and creates an alert box with the text of the user input.
http://jsfiddle.net/a8FHg/1/
For completness if jsfiddle doesn't work some day. You JavaScript should looks like this.
dojo.ready(function(){
var form = dijit.byId('form');
var box = dijit.byId('box');
var submit = function(event) {
dojo.stopEvent(event);
alert("User input was " + box.get('value'));
};
dojo.connect(form, 'onSubmit', submit);
});
Assuming your form in your HTML has the id form and your box have the id box.