SHAppBarMessage and AutoHide - java

public void toggleAutoHide()
{
APPBARDATA data = new APPBARDATA.ByReference();
data.hWnd = hWndGlobal;
data.cbSize.setValue(data.size());
data.lParam.setValue(Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_GETSTATE), data).longValue());
data.lParam.setValue(data.lParam.intValue() ^ 0x0000001);
UINT_PTR result = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_SETSTATE), data);
}
I have the code above that is supposed to autohide a created appbar, but somehow instead of doing this to the actual bar I'm creating, it's actually changing the status of the main Windows taskbar. Any clue what step I'm missing?
EDIT:
I've modified the code and changed the call but I'm getting the same values all the time, regardless of what I set the values to.
public void toggleAutoHide()
{
APPBARDATA data = new APPBARDATA.ByReference();
data.hWnd = hWndGlobal;
data.cbSize.setValue(data.size());
data.uEdge.setValue(ShellAPI.ABE_TOP);
System.out.println("LParam [byte, int]: " + data.lParam.byteValue() + " -- " + data.lParam.intValue());
//lParam always shows 0
if(data.lParam.intValue() == 1)
{
data.lParam.setValue(0);
}
else
{
data.lParam.setValue(1);
}
UINT_PTR result = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_SETAUTOHIDEBAR), data);
System.out.println("Result = " + result.intValue()); //always returns 1
}

The ABM_SETSTATE call is using your data.hWnd variable to decide which window handle gets your changes. You assign that to the value a variable hWndGlobal but don't explain where that came from.
The fact that it's named "global" seems to imply somewhere earlier in the code you gave it the value for the Windows taskbar. Hunt down that assignment.
You probably want something like:
data.hWnd = User32.INSTANCE.FindWindowA(null, "Title of your new appbar");

Related

Function not ending correctly after recursive loop

I am trying to build a copy cat of the game risk. I have a while loop which says while the attack isn't finished do something. Then I ask the user to type in either 'end turn' to end turn or 'continue' to recursively call the attack function again. The problem is after the user types in attack a few times and then 'end turn' the turn doesn't end rather it starts from the beginning or the function again. I would greatly appreciate an expert eye to look at my code and see what I am missing, thanks in advance.
public void attackOrSkip(Player player,Player[] playerArray, int playerId) {
boolean attackFinished = false;
int numUnitsAttackWith = 0;
int defenceArmiesNumber =0;
displayString(makeLongName(player) + ": Type 'attack' to attack or 'skip' to skip your turn...");
String command = commandPanel.getCommand();
displayString(PROMPT + command);
if(command.equals("skip") ||command.equals("skip ") ||command.equals("s")) {
return;
}else if (command.equals("attack") ||command.equals("attack ")){
displayString(PROMPT + command);
//while the attack isn't finished
while(attackFinished == false) {
//get the country the user is attacking
int countryAttackingFrom=countryFromCheck(playerId,player);
//get the country to attack
int countryToAttack = countryToCheck(player);
//get the player who we are attacking
int occupierPlayer =board.getOccupier(countryToAttack);
if ((board.getNumUnits(countryAttackingFrom)) < 2) {
displayString("You dont have enough units on this country to make an attack!");
attackOrSkip(player, playerArray, playerId);
break;
}
//if the country is adjacent to another one then you can attack else no
else if(isAdjacent(countryAttackingFrom,countryToAttack)) {
//check the number of unit to attack with
numUnitsAttackWith =numUnitsCheckerAttack(player,countryAttackingFrom);
//check the number of unit to defend with
defenceArmiesNumber = numUnitsCheckerDefence(player,countryToAttack);
//roll the dice
player.rollDice(numUnitsAttackWith);
playerArray[occupierPlayer].rollDice(defenceArmiesNumber);
//display the roll results
displayString(makeLongName(player) + "Rolled: "+printDie(player));
displayString(makeLongName(playerArray[occupierPlayer]) + "Rolled: "+printDie(playerArray[occupierPlayer]));
}
displayString(makeLongName(player) + ": 'end turn' or 'continue'");
command = commandPanel.getCommand();
displayString(PROMPT + command);
if(command.equals("end turn")||command.equals("end turn ") ||command.equals("endturn")||command.equals("endturn ") ||command.equals("end")) {
attackFinished = true;
return;
}else if(command.equals("attack") ||command.equals("attack ")){
// break;
}else if(command.equals("continue") ||command.equals("continue ") ||command.equals("con")){
attackOrSkip(player,playerArray,playerId);
}else {
return;
}
}else {
displayString(makeLongName(player) + ": ERROR, not adjacent countries");
}
}
}
}
Okay - as currently written - every time you call attackOrSkip within the method - you end up 1 level lower in the stack - with a new set of variables -
attackFinished, numUnitsAttackWith, defenceArmiesNumber
When you leave the recursion (i.e. via a return) you end up with simple variables as they were before you enter the recursive call - remember Java is Call By Value (even though you can pass in references to objects, you get a value (the current value of the variable reference when called ... and changing the reference to point at a different object doesn't change the callers reference).
SO, without looking to see whether you have done the correct algorithm - I would guess that if you made the method return type a boolean and returned the status instead of nothing, you could update attackFinished and the right thing might happen..
e.g. change all the
return;
to
return attackFinished;
AND change all the places where you call
attackOrSkip(....)
to set attack finished based on what the method return
attackFinished = attackOrSkip(....)
OR - you can pass in an extra parameter - attackFinished - in a Holder (an example of the concept) object - again the reference can't change, but you can go attackFinished.value = true (and it will then be the same the whole way out the stack as you drop out of the recursion).

RasEnumConnections function in JNA is returning incomplete data. What I am doing wrong?

RasEnumConnections function which realized in JNA is returning incomplete data.
What wrong? This is my code:
public static void main(String[] args) {
Connected();
}
private static void Connected () {
boolean state = false;
ArrayList<String> connectedNames = new ArrayList<>();
IntByReference lpcb = new IntByReference(0);
IntByReference lpcConnections = new IntByReference(0);
Rasapi32.INSTANCE.RasEnumConnections(null, lpcb,lpcConnections);
WinRas.RASCONN conn = new WinRas.RASCONN();
conn.dwSize = lpcb.getValue();
WinRas.RASCONN[] connArray;
if(lpcConnections.getValue() > 0)
connArray = (WinRas.RASCONN[])conn.toArray(lpcConnections.getValue());
else
connArray = (WinRas.RASCONN[])conn.toArray(1);
System.out.println("lpcb: " + lpcb.getValue() + " lpcConnections: " + lpcConnections.getValue() + " RASCONN Size: " + conn.dwSize);
int error = Rasapi32.INSTANCE.RasEnumConnections(connArray, lpcb,lpcConnections);
if(error == WinError.ERROR_SUCCESS) {
System.out.println("Entry name: " + Native.toString(connArray[0].szEntryName)
+ " Guid string: " + connArray[0].guidEntry.toGuidString());
System.out.println(connArray[0].guidEntry.Data1);
System.out.println(connArray[0].guidEntry.Data2);
System.out.println(connArray[0].guidEntry.Data3);
}
else System.out.println("Error: " + error);
WinRas.RASENTRY.ByReference entry = getPhoneBookEntry("test1");
if(entry != null) {
System.out.println("test1 guid: "+ entry.guidId.toGuidString());
System.out.println(entry.guidId.Data1);
System.out.println(entry.guidId.Data2);
System.out.println(entry.guidId.Data3);
}
else System.out.println("Error: " + Native.getLastError());
}
}
Char array szEntryName contains only 3 last chars of connection name. (Connection name is "test1")
As I've noted in the comments, the debug output gives you a strong hint at what's happening. The missing "t" and "e" characters appear as 0x74 and 0x65 in the midst of what JNA expects to be a 64-bit pointer. The logical conclusion is that Windows is returning a 32-bit pointer followed by the string, 4 bytes earlier than JNA expected.
RasEnumConnections states a few things regarding the buffer you are passing as connArray:
On input, an application must set the dwSize member of the first
RASCONN structure in the buffer to sizeof(RASCONN) in order to
identify the version of the structure being passed.
In your sample code above you are leaving this value the same as the value from the initial return. This is specifying the "wrong" version of the structure. Instead, you should set the dwSize member to the size you want in your JNA structure:
conn.dwSize = conn.size();
Actually, the constructor for RASCONN sets this for you! So you actually don't have to do this. But in your code sample above, you are overwriting what was pre-set; just delete your conn.dwSize line.
Note that since you are now requesting a (4-bytes per array element) larger buffer by definining the structure size, you also need to pass the increased size in the (second) RasEnumConnections() call. It's set as the number of elements times the (smaller) structure size, but you should reset to the number of elements times the (larger) size like this:
lpcb.setValue(conn.size() * lpcConnections.getValue());
prior to fetching the full array. Otherwise you'll get the error 632 (Incorrect Structure Size).
For reference (or perhaps a suitable replacement for your own code), take a look at the code as implemented in the getRasConnection(String connName) method in JNA's Rasapi32Util.java class.

Java method design pattern

I'm developing a program that scrapes the web for certain data and feeds it back to the database. The problem is that I don't want duplicate entries of the same data as soon as the crawlers run for a second time. If some attributes changed, but the majority of the data is still the same, I'd like to update the DB entry rather than simply adding a new one. I know how to do this in code, but I was wondering if this could be done better.
The way the update works right now:
//This method calls several other methods to check if the event in question already exists. If it does, it updates it using the id it returns.
//If it doesn't exist, -1 is returned as an id.
public static void check_event(Event event)
{
int id = -1;
id = check_exact_event(event); //Check if an event exists with the same title, location and time.
if(id > 0)
{
update_event(event, id);
Logger.log("EventID #" + id + " found using exact comparison");
return;
}
id = check_similar_event_titles(event); //Check if event exists with a different (but similar) title
if(id > 0)
{
update_event(event, id);
Logger.log("EventID #" + id + " found using similar title comparison");
return;
}
id = check_exact_image(event); //Check if event exists with the exact same image
if(id > 0)
{
update_event(event, id);
Logger.log("EventID #" + id + " found using image comparison");
return;
}
//Otherwise insert new event
create_new_event(event);
}
This works, but it's not very pleasing to the eye. What's the best way to go about this?
Personally i can'tsee anything wron with your code, it is clean and effective.
If you really want to change it, you could do it in single if statement
public static void check_event(Event event) {
int id = -1;
if ((id = check_exact_event(event)) > 0
|| (id = check_similar_event_titles(event)) > 0
|| (id = check_exact_image(event)) > 0) {
update_event(event, id);
}
;
create_new_event(event);
}
But i cant see much gain in this way

InvocationTargetException while trying to add variables to a new object

I am trying to send two variables from one sketch to another, using the oscP5 library for processing.
The message I am sending is created like this:
OscMessage myMessage = new OscMessage("/test");
myMessage.add(title);
myMessage.add("Zeit");
oscP5.send(myMessage, remoteLocation);
In the second sketch, I receive the data like that:
void oscEvent(OscMessage theOscMessage) {
if(theOscMessage.checkAddrPattern("/test")) {
String title = theOscMessage.get(0).stringValue();
String layoutType = theOscMessage.get(1).stringValue();
addToQueue(title, layoutType);
}
}
And here my simplified addToQueue function:
void addToQueue(String title, String layoutType) {
if(!existsInQueues(title)) {
upcomingHeadlines.add(new Headline(title, printAxis, scrollSpeed, layoutType));
}
}
Every time I start the sketches, I get the error:
ERROR # OscP5 ERROR. an error occured while forwarding an OscMessage to a method in your program. please check your code for any possible errors that might occur in the method where incoming OscMessages are parsed e.g. check for casting errors, possible nullpointers, array overflows ... .
method in charge : oscEvent java.lang.reflect.InvocationTargetException
I have been able to track the problem down to the layoutType-Variable. If I change
String layoutType = theOscMessage.get(1).stringValue();
to
String layoutType = "Zeit";
no error occurs.
That is quite confusing, because both versions should have the same result.
The error message does not help me in any way.
Edit
I have compared the two possible variables like that:
String layoutType = theOscMessage.get(1).stringValue();
String layoutTypeB = "Zeit";
if(layoutType.equals(layoutTypeB)) println("Same String!");
Since gets printed to the console, both have to be the same … I really do not know where to search for an error anymore.
Edit 2
I have wrapped my second sketch in try {...} catch(Exception ex) {ex.printStackTrace();} like that:
void oscEvent(OscMessage theOscMessage) {
try {
if(theOscMessage.checkAddrPattern("/test")) {
if(debug && debugFeed) println("Received message from other sketch.");
String title = theOscMessage.get(0).stringValue();
String layoutTypeO = (String)theOscMessage.get(1).stringValue();
String layoutType = "Zeit";
if(debug && debugTemp) {
if(layoutType.equals(layoutTypeO)) println("IS DOCH GLEICH!");
}
if(debug && debugFeed) println("Parsed Information.");
if(debug && debugFeed) println("-----");
addToQueue(title, layoutTypeO);
}
} catch(Exception ex) {ex.printStackTrace();}
}
That gives me this error as result:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at printer$Headline.useLayout(printer.java:260)
at printer$Headline.<init>(printer.java:188)
at printer.addToQueue(printer.java:407)
at printer.oscEvent(printer.java:395)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at oscP5.OscP5.invoke(Unknown Source)
at oscP5.OscP5.callMethod(Unknown Source)
at oscP5.OscP5.process(Unknown Source)
at oscP5.OscNetManager.process(Unknown Source)
at netP5.AbstractUdpServer.run(Unknown Source)
at java.lang.Thread.run(Thread.java:744)
Edit 4
Constructor for my Headline-Class:
class Headline {
//Define Variables
Layout layout;
String title, lastHeadline;
float yPos, speed;
float transparency = 255;
boolean fullyPrinted = false;
int boundingBoxHeight;
// Initialize Class Function
Headline(String t, float y, float s, String lay) {
title = t;
yPos = y;
speed = s;
layout = useLayout(lay);
boundingBoxHeight = calculateTextHeight(title);
}
You might want to know about useLayout() too, so here it is:
Layout useLayout(String name) {
ArrayList layoutVariants = new ArrayList<Layout>();
int existingLayouts = layouts.size();
Layout chosenLayout;
for(int i = 0; i < existingLayouts; i++) {
Layout currentLayout = (Layout)layouts.get(i);
if(currentLayout.layoutType == name) {
layoutVariants.add(currentLayout);
}
}
if(layoutVariants != null) {
int rand = (int)(Math.random() * layoutVariants.size());
chosenLayout = (Layout)layoutVariants.get(rand);
} else {
chosenLayout = (Layout)layouts.get((int)(Math.random() * existingLayouts));
}
return chosenLayout;
}
There are two problems with your code, and both of them are in your useLayout method.
The first problem is that you are not comparing Stringss correctly on this line:
if(currentLayout.layoutType == name) {
name is a String, and I assume currentLayout.layoutType is too. Two Strings that are equal but not the same will not compare equal under ==. As a result of this, your layoutVariants list will quite probably be empty at the end of the for loop.
This line should read:
if(currentLayout.layoutType.equals(name)) {
See also this question.
The second problem is that you don't correctly handle the case that the layoutVariants list is empty. The problem is on this line:
if(layoutVariants != null) {
layoutVariants will never be null, so the else branch of this if statement will never execute. Because layoutVariants.size() will be zero, rand will always be zero. Trying to get the element at index 0 in an empty ArrayList will give you precisely the IndexOutOfBoundsException you are seeing.
I imagine you want the else block to execute if the layout name given isn't recognised, in other words, if the layoutVariants list is empty, rather than null. In that case, change this line to
if(!layoutVariants.isEmpty()) {
Note the ! (not-operator) before layoutVariants. You want the code under the if statement to run if the layoutVariants element is not empty.
EDIT in response to your comments: a null ArrayList is very much not the same as an empty one. null is a special value meaning that the variable doesn't have an object of a given type.
Let's try a real-world analogy: a shopping bag. If you have an empty bag, or no bag at all, then you have no shopping either way. However, you can put things into an empty bag, and count how many items it contains, for example. If you don't have a bag, then it doesn't make sense to put an item in it, as there's no bag to put the item into. null represents the case where you don't have a bag.
Similarly, a String is a collection of characters, and the collection of characters can exist even if it doesn't contain any characters.
isEmpty() can be used for any collection, and, if you're using Java 6 or later, Strings as well. Off the top of my head I can't name any other classes that have an isEmpty method. You'll just have to consult the documentation for these classes to find out.
I've not worked with Processing much, but I am aware that Processing is built on Java, so I would expect any standard Java method to work. Also, I wouldn't worry about 'clearing' a variable: the JVM is generally very good at clearing up after you. There's certainly nothing I can see wrong with your code in this respect.
EDIT 2 in response to your further comment: ArrayList arr; declares a variable of type ArrayList. However, the variable arr is uninitialized: it does not have a value (not even null) and it is an error to try to read the value of this variable before you have assigned a value to it:
ArrayList arr;
System.out.println(arr); // compiler error: arr might not have been initialised.
Assign null and the code then compiles:
ArrayList arr = null;
System.out.println(arr); // prints 'null'.
It's not often you need to declare a variable and not give it a name, but one common case is where you want to assign different values to the same variable on both sides of an if statement. The following code doesn't compile:
int y = getMeSomeInteger(); // assume this function exists
if (y == 4) {
int x = 2;
} else {
int x = 5;
}
System.out.println(x); // compiler error: cannot find symbol x
The reason it doesn't compile is that each variable x is only available within the braces { and } that contain it. At the bottom, neither variable x is available and so you get a compiler error.
We need to declare x further up. We could instead write the following;
int y = getMeSomeInteger(); // assume this function exists
int x = 0;
if (y == 4) {
x = 2;
} else {
x = 5;
}
System.out.println(x);
This code compiles and runs, but the value 0 initially assigned to x is never used. There isn't a lot of point in doing this, and we can get rid of this unused value by declaring the variable but not immediately giving it a value.
int y = getMeSomeInteger(); // assume this function exists
int x;
if (y == 4) {
x = 2;
} else {
x = 5;
}
System.out.println(x);

Does "return" stop the execution of a method?

I have programmed a method in the following way:
if (something) {
return 1;
}
the rest of the code
It seems to me that the method returns 1 and then execute the rest of the code. Can it be the truth? Doesn't return stops the execution of the code. It it is not, how can I force a method to stop?
ADDED
Here is the code (as requested):
for (int i=availableTime; i>0; i=i-1) {
final int sec = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
String lbl = "<html>";
lbl += "</html>";
timeLeftLabel.setText(lbl);
}
});
try {Thread.sleep(1000);} catch (InterruptedException e) {}
parameterFromClientsListener = clientsListener.getValue(userName,parameterToGet);
if (!parameterFromClientsListener.equals("null")) {
output = parameterFromClientsListener;
game.log.fine(userName + " set (by button) " + parameterToGet + " to be equal to " + output + " . [IMPORTANT]");
return output;
}
}
game.log.fine("The partner selection phase is expired.");
// This code is executed if the Submit button was not pressed and the time run out.
if (parameterToGet.equals("partner")) {
tellMyChoice(parameterToGet, this.partnerFromForm, "timer of" + field);
output = this.partnerFromForm;
}
game.log.fine(parameterToGet + " was submitted by timer (not by OK button).");
} else {
output = parameterFromClientsListener;
}
game.log.fine(userName + " set (by timer)" + parameterToGet + " to be equal to " + output + " . [IMPORTANT]");
return output;
}
I run this code two times. In every case I generate a log-file. In both log files I see "set (by button)" statement (which is straight before the return). But the problem is that in the second log file I do see "timer of" statement. Which should not be reached if the "set (by button)" is reached. How can it be? I need to mention that "set (by button)" and "timer of" do not occur anywhere else in my code (they occur only once).
ADDED 3
As you can see from the code I do not have the finally statement.
This is not true, the return statement will stop any following code. (With the only exception being that the return statement is in a try{} block that has a finally{} block afterwards.
if(0==0){
return;
}
System.out.println("This will not print.");
return does end the execution of the method. There is one exception: the finally block. In the following case, 2 would be returned
public int foo() {
try {
return 1;
} finally {
return 2;
}
}
Return does indeed end the execution of a method. Check Your other assumptions. Maybe something in other parts of code isn't working as You are assuming.
Does return stops the execution of the code
well, almost.
Once a return is encountered, the method execution is stopped, and the control is passed to the calling method, after executing any finally clauses.
int add(int a, int b)
{
try{
if(a == 0)
{
return b;
}
if(b == 0)
{
return a;
}
return a+b;
}
finally
{
System.out.println("Finally");
}
}
In the above code, is the function is called as add(0, 1), "Finally" will still be printed.
How can I force a method to stop?
OR What are the other ways of exiting from a method?
Exceptions
You write
if (!parameterFromClientsListener.equals("null")) {
output = parameterFromClientsListener;
game.log.fine(userName + " set (by button) " + parameterToGet + " to be equal to " + output + " . [IMPORTANT]");
return output;
}
You are comparing the string (or whatever) with the string "null", and return if they are different. Do you really want to do this, and not parameterFromClientsListener != null?
(Though that should not be a big difference, as long as parameterFromClientsListener is neither null nor "null", and if it is null, your version would give a NullPointerException.)
Do you actually get the entry in your log file? If so, you should also get the return.
I wanted to understand how the observed behavior can be possible. In more details, I saw a "paradoxical" behavior. In my log files I saw output of the line which happens before the return as well as the output produced by the code after the return. So, I assumed that the return does not stop the execution of the program. As it has been correctly mentioned here by other "answerers" this assumption is wrong. The explanation of the behavior is trivial. My program run the shown code several times. The first time it reaches the return statement, the second time it passes it (because the return is in the if statement). So, it is why IO have the both statements in the log file.

Categories

Resources