Create a Resolution Independent Form in ms access - forms

I have designed my form in 1280*1024 resulotion. They lookvery nice on my Monitor, but If I see on another Monitors, they look very chaotic . Is there a way that I solve this problem?

It's not so easy. This is where MVC comes in very handy and you can distinguish between different components. You can have different views for different devices. Unfortunately VBA does not support that and you would have to implement your own framework to handle different screen resolutions.
The easiest way to avoid having to re-implement the design of your userform is to actually DESIGN it in your head before writing a single line of code. Think of the different resolutions(devices) your software is going to support, what the language you are using is supporting and what are your choices. Generally, think it over. In VBA I normally just go for the default size to avoid the headache of fitting someone's else screen.
You would have to redesign the entire UserForm. Not visually, but programmatically set both width, and height of the userform and make controls dependable on the current resolution. I do not recommend doing it this way but still this could be a solution.
You can achieve that by accessing the current resolution and modifying your Userform_Initialize() event.
So example, if the current resolution is 1024x768, you set the width and height to currentWidth-100px and currentHeight-100px.
If you open a new workbook and create an empty userform. Go to its code behind and add
Private Sub UserForm_Initialize()
Me.Width = GetCurrent(0) - 600
Me.Height = GetCurrent(1) - 800
End Sub
Then insert a module and add
Private Declare Function GetSystemMetrics Lib "user32.dll" (ByVal nIndex As Long) As Long
Sub A()
UserForm1.Show
Unload UserForm1
End Sub
Function GetCurrent(x As Long) As Long
GetCurrent = GetSystemMetrics(x)
End Function
This will display a different size userform depending on the current resolution.
you can (but I wouldn't recommend it) use that technique. Note: depending on how many controls you have this may be the best approach but if you have lots of controls on the userform I would look for an alternative.
Alternatively, you can use the below code which checks the current screen resolution, warns the users and asks if the user wants to change his resolution.
The below code comes from here and the original author is DRJ
You stick the first part in the Workbook code behind
Option Explicit
Private Sub Workbook_Open()
Call VerifyScreenResolution
End Sub
and the below part in a module
Option Explicit
Private Declare Function GetSystemMetrics Lib "user32.dll" (ByVal nIndex As Long) As Long
Const SM_CXSCREEN = 0
Const SM_CYSCREEN = 1
Sub VerifyScreenResolution(Optional Dummy As Integer)
Dim x As Long
Dim y As Long
Dim MyMessage As String
Dim MyResponse As VbMsgBoxResult
x = GetSystemMetrics(SM_CXSCREEN)
y = GetSystemMetrics(SM_CYSCREEN)
If x = 1024 And y = 768 Then
Else
MyMessage = "Your current screen resolution is " & x & " X " & y & vbCrLf & "This program " & _
"was designed to run with a screen resolution of 1024 X 768 and may not function properly " & _
"with your current settings." & vbCrLf & "Would you like to change your screen resolution?"
MyResponse = MsgBox(MyMessage, vbExclamation + vbYesNo, "Screen Resolution")
End If
If MyResponse = vbYes Then
Call Shell("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3")
End If
End Sub
update.
your initialize event is here

Related

Macro syntax failure in attachmate extra

I've been scrubbing google to find a quick reference for macro coding in Attachmate extra! unsuccessfully. Could someone point me to a URL to learn what I need to know, tell me how to resolve the code below or both.
I took a "Hello World" example and a recorded macro and mushed the below code together, which does what i need with a couple exceptions.
Dim dlgHello as HelloDialog 'Declare the dialog file.
nRet = Dialog (dlgHello)
Select Case nRet 'dlgHello.AllButtons
Case - 1 ' OKButton
Sess0. Screen. Sendkeys ("Show a60:4aug;a")
Sess0. Screen. Sendkeys("<Enter>")
Sess0. Screen.WaitHostQuiet (g HostSettleTime)
System. Timeoutvalue = OldsystemTimeout
Msabox "Done"
Case 0 ' CancelButton
Msgbox "Goodbye! "
End Select
While this code above works, I need to change it to pull system date and subtract two days.
Original code Sess0. Screen. Sendkeys ("Show a60:4aug;a")
Instead of the static 4aug, I need the code to pull the system date then subtract two days.
My failed attempt was Sess0. Screen. Sendkeys ("Show a60:"Today() -2"a")
Would be grateful if anyone could tell me how to resolve this and also point me to a good learning resource. Thanks
I received a working solution from Tom F in the MicroFocus community. Solution below.
Sub Main
Dim myDate
myDate=CVar(Date)-2
myDate = Format(myDate, "dmmm")
End Sub
https://portal.microfocus.com/s/article/KM000008384?language=en_US

Coverting between javascript keycodes and libgdx keycodes

I am porting a existing webgame to libgdx. The game is controlled by a script I would rather not change.
The script specifies actions to do on certain keypress events using their javascript keycode value.
ie. "OnKeyPress=32:" would define actions to run when space is pressed.
"OnKeyPress=40:" would define actions to run when down is pressed, etc.
Now, as LibGDX uses different keycode system I need some way to fire my existing events when the correct key is pressed.
#Override
public boolean keyDown(int keycode) {
//convert input processors keycode to javascripts?
}
I can only think I have to create some sort of large static hashmap mapping between
GDXs
Input.Keys
and
com.google.gwt.event.dom.client.KeyCodes
But before going to this bother I thought Id ask around in case theres a better way?
Thanks,
In the end I just created a class to associate one keycode (com.badlogic.gdx.Input.Keys) with another. (com.google.gwt.event.dom.client.KeyCodes)
Fairly easy, but anyone doing the same should pay careful attention that not everything has a 1:1 mapping.
For example;
ALT_LEFT and ALT_RIGHT both map to ALT in gwt/javascript.
Likewise CNTR left and right and SHIFT left and right.
GDX meanwhile treats BACKSPACE and DELETE as the same key.
This is, naturally, as GDX needs to be cross platform so has different requirements.
Other then that just a ImmutableMap seemed to do the job....
/**
* static mapping between javascript/gwt keycodes and gdxs
**/
static ImmutableMap<Integer,Integer> keyCodeConversion = ImmutableMap.<Integer, Integer>builder()
.put(Input.Keys.UP, GwtKeyCodeCopy.UP)
.put(Input.Keys.DOWN, GwtKeyCodeCopy.DOWN)
.put(Input.Keys.LEFT, GwtKeyCodeCopy.LEFT)
.put(Input.Keys.RIGHT, GwtKeyCodeCopy.RIGHT)
.....
...(lots more)
.bind();
static public int getJavascriptKeyCode(int GdxKeycode){
return keyCodeConversion.get(GdxKeycode);
}

Calling form that runs in a loop from a command button

I want to run a form called PostFlight, from a command button on a spreadsheet, the form will run for a number of entry cycles.
So currently I have a commandbutton click that calls the form called PostFlight successfully.
Private Sub CommandButton1_Click()
Counter = 0
BatteryAmp = Application.InputBox(Prompt:="What is battery Amps?")
Range("AC1").Value = BatteryAmp
BatteryCounter = Application.InputBox(Prompt:="How many batteries?")
Range("AA204").Value = BatteryCounter
PostFlight.Show
End Sub
The form called Postflight works exactly as I want it to as a standalone form.
My question is where to place the loop and where to define the variables of that loop.
I know that I want to define a Counter as an Integer and the loop must run until it reaches the BatteryCounter value. But where to place the loop?
Do I place it in the declarations alongside the Private Sub CommandButton1_Click()
OR
Do I place it in the form code and if I place it in the form code, does it make a difference as to where in the code I place the loop.
I have tried to increment and display a counter in the code of the form
Counter = Counter + 1
Range("AA205").Value = Counter
But it does not work for some or other reason.
Hopefully you are able to assist me.
Thanks in advance.
If I understand what you want correctly, this should work:
Private Sub CommandButton1_Click()
Dim Counter as Integer
BatteryAmp = Application.InputBox(Prompt:="What is battery Amps?")
Range("AC1").Value = BatteryAmp
BatteryCounter = Application.InputBox(Prompt:="How many batteries?")
Range("AA204").Value = BatteryCounter
For Counter = 1 to BatteryCounter
PostFlight.Show
Next
End Sub
I did a mini-test with this code and it worked. However, you will need to make sure the button on your Form that fills the cells with entries has the line PostFlight.Hide after it finishes filling the cells, or after the Form is done doing everything you want it to do.

Some beginner questions

I guess I'll start by saying I am very new to B4A, and to programming in general. I have some very basic java and html exp. but that's it. I do not have any basic4ppc or really any IDE experience. Been using B4A for a few days now and can't get over the hump. Here are my noob questions:
Does having many activities (20-30+) slow down the app? Is there a downside to having a lot of activities?
I can't figure out how to scroll in the designer. I am trying to make a screen that has 25 buttons down in 1 column. However I can't scroll down to add more buttons below. I am able to add buttons programmically and in the fashion that I want (using a for loop), but is it normal to create views at runtime like this?
How do you ensure your app looks the same across all devices? Tablets? I have a scroll view that fits perfect in the emulator, but on my phone (droid x), the bottom of the scroll view is not stretched to the bottom of the phone. I use the code: scvScreen1.Initialize(100%y). Is that not right?
I have a Email screen in which is comprised of an edittext and a Send button, so that the users can send me questions from the app. However the Send button gives me this error on the 'URI =' line: "LastException java.lang.NumberFormatException: mailto:" here is the code:
Sub btnSendEmail_Click
Dim Uri As String
Uri="mailto:me#gmail.com?subject=Test Email&body=" + edtHelpEmail.Text
Dim Intent1 As Intent
Intent1.Initialize(Intent1.ACTION_VIEW,Uri
StartActivity(Intent1)
End Sub
Or is there another way to open the device's default email program?
Regarding last question, how do I copy error messages to clipboard?? I selected the red error message on the bottom right of the IDE and tried ctrl-c, but didn't work.
In B4A, what is a good method of storing persistent data? All I really need to store are some strings. Nothing fancy. These strings are to be stored locally. AI made this easy by using TinyDB.
When using the designer, how do you ensure your views are centered on all devices? For instance, I have a screen that has several rows made up of: (label, edittext, label). And I want each row to be center aligned. Do I do this programmically? I'm thinking I would have to append each row of (label, edittext, label) to a panel, then in the code center the panel. Is this correct?
That's all I got for now, but I'm sure there will be plenty more questions later.
1) The whole idea of android is to small components i.e. Apps working together, so no need to worry about opening lots of activities. Memory is very well managed behind the scenes in Android.
2) Sure. That sounds fine to me. Use the Layout designer as much as you can and then add the dynamic stuff later. It's all about striking a balance between the size of your code and the number of activities.
3) In the Designer there's an option called 'Send to UI Cloud'. This compares your app over multiple screen sizes. You can also scale your design and programmatically resize specific controls within your app in the Activity_Create Lifecycle
4) What you're doing is almost correct. I corrected your code:
Sub MailTo(StrAddress As String, StrSubject As String, StrBody As String)
Dim StrMethod As String = "Sub MailTo(StrAddress As String, StrSubject As String, StrBody As String)"
Try
Dim StrUri As String
StrUri = "mailto:" & StrAddress & "?subject=" & StrSubject & "&body=" & StrBody
Dim Intent As Intent
Intent.Initialize(Intent.ACTION_VIEW, StrUri)
StartActivity(Intent)
Catch
If BlnLoudExceptions Then CdException.Show(StrClass, StrMethod, LastException)
End Try
End Sub
I tend to have a code module called CdIntent.bas for these functions as it both keeps the project organised and makes it easier to implement the same functionality across projects.
Then to call you would use
CdIntent.MailTo("me#yes.no", "Subject!", "Body!")
5) I have a file called CdException.bas
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
End Sub
Sub Show(StrClass As String, StrMethod As String, Ex As Exception)
LogColor("Exception: " & Ex.Message & " - Class: " & StrClass & " - Method: " & StrMethod, Colors.Magenta)
End Sub
and then wrap functions in the following way:
Sub FunctionName(...Parameters...) as Int
Dim StrMethod As String = "Sub Sleep(LngMilliseconds As Long)"
Dim IntResult As Int = 0
Try
[code here inc. IntResult = ???]
Catch
If BlnLoudExceptions Then CdException.Show(StrClass, StrMethod, LastException)
End Try
Return IntResult
End Sub
BlnLoudExceptions is a global boolean that you'd declare in
Process_Globals that you can switch on an off exception logs.
StrClass is a global String that you'd declare in Process_Globals
that contains the name of the class e.g. "CdIntent.bas"
The exceptions then appear in magenta in the log screen along with the method name and class in which they occurred allowing you to home in on them.
6) I have a table in an SQLLite database called TabletSettings, which has two TEXT colums called 'Name' and 'Value'. It works well and gets you into a (what I think is a) good habit of always having a database available to your app from the get-go.
7) I'll get back to you on this as I haven't done this before.
Until then, the following thread will help you in the B4A forum http://www.basic4ppc.com/android/forum/threads/convert-integer-to-dip.18800/
I agree with Jim's point but will attempt to answer 1.
I'm new to android myself but as I understand it activities on the whole are only running when active. Unless you are using the app to continuously do something there is only one activity at a time. The number of activities is likely to affect the ram available more than anything. Lastly it might be worth walking first rather than running so to speak but trying a single and then add multiple activities.
You could try adding a ListView or ScrollView where the items are the buttons, this seems to be the std way of doing things otherwise a tabbed view.

Saving and reading int values in case of app close

I've created an application which contains settings as int values... Basically my app contains multiple layouts. When the user presses the "back" key, the app returns to the first panel (which is the main screen!). If pressed on the main screen, the app will pause/finish.
The integer values that I have are what I use to determine whether the user has done something in the app. They also determine which layout the user is in.
I really need to have these int values for when the user opens the app again. What is the best way that I should go about saving multiple int values so that I can access them if the app is killed?
Thanks
Sorry... I'm finding it really hard to write and read to and from a map file... Here is what I have so far simplified. Can you see if I am missing something... more than likely its really easy.
Sub Activity_Resume
Dim m As Map
m.Initialize
If File.Exists(File.DirInternal, "1.txt") Then
m = File.ReadMap(File.DirInternal,"1.txt")
int1 = m.Get("int1")
int2 = m.Get("int2")
End If
End Sub
Sub Activity_Pause (UserClosed) As Boolean
Dim m As Map
m.Initialize
m.Put("int1", int1)
m.Put("int2", int2)
File.WriteMap(File.DirInternal, "1.txt", m)
End Sub
You have several options. You can use StateManager or you can store the settings in a Map and then in Activity_Pause save the Map with File.WriteMap, and read the Map in Activity_Create if the file exists.