I have a window service for my application. When i stops that by killing process with task manager, the tray icon does not disappear. Is it a window bug or something else? Do we have a solution for that problem? Thanks in advance :).
You can let the icon disappear by calling the Dispose()-method of the specified NotifyIcon-object. In most cases these Container-object isn't part of the tree of components in your application so it will not disappear by killing the proces. When the user moves over the icon, the icon doesn't find it parent so it dissapears. But by calling the Dispose-method, it disapeared at least in my applications. So:
//creating a NotifyIcon
NotifyIcon notifyicon = new NotifyIcon();
notifyicon.Text = "Text";
notifyicon.Visible = true;
notifyicon.Icon = new Icon(GetType(),"Icon.ico");
//let it disappear
notifyicon.Dispose();
There is no solution to this problem. If you kill process with task manager, it does not receive termination notification, and hence can not remove its icon from the tray. Try avoiding killing process this way. You can use net start/stop to kill a service or services.msc GUI.
Use this tool http://www.codeproject.com/Articles/19620/LP-TrayIconBuster
It iterates through ToolBarButtons in TrayNotifyWnd & NotifyIconOverflowWindow and removes those with null file names.
Move your mouse over the icon, and it will disappear. I've noticed this behavior in all versions of windows, including Win 7.
I often notice that too, with various applications. The death of the application is only noticed when you move the mouse over the icon.
I think the "bug" is with Windows, not your application. (I'm reluctant to call it a "bug", per se, because it was probably a conscious decision to leave this in. Explorer could check whether applications that registered icons are still running, but that might be too expensive.)
If an application is forcefully terminated (e.g. through Task Manager), then Windows does not remove the notification icon. Windows Explorer doesn't even notice that the application has gone away until it attempts to send a message (usually a mouse movement message) to the window that owns the notification icon. At that point, Windows will remove the now dead icon from the notification area.
Given that you can't intercept TerminateProcess, there's nothing that your program can do about this by itself.
I guess that Windows Explorer could watch for the owner window being destroyed (as when the application quits unexpectedly), but it doesn't.
Even if the application is shut down gracefully, it must still remember to remove any of its notification icons. That is: if you don't call Shell_NotifyIcon(NIM_DELETE) (the equivalent of NotifyIcon.Dispose) when your application shuts down (even gracefully), the icon will remain there until the mouse moves over it.
Oh, and if this is a service process that's displaying the notification icon, be aware that session 0 isolation in Windows Vista and Windows 7 will break it.
You can move your mouse over it, or you can send a WM_MOUSEMOVE message to it.
Here is some sample code (tested on Windows 10):
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left, Top, Right, Bottom;
}
[DllImport("user32.dll")]
static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr hWndChildAfter, string className, string? windowTitle);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, nuint wParam, nint lParam);
const int WM_MOUSEMOVE = 0x0200;
public static void RefreshTraybar()
{
RefreshHiddenTraybar();
RefreshTraybarInTaskbar();
}
static void RefreshHiddenTraybar()
{
var hiddenTrayWnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "NotifyIconOverflowWindow", null);
var hiddenNotificationArea = FindWindowEx(hiddenTrayWnd, IntPtr.Zero, "ToolbarWindow32", null);
RefreshArea(hiddenNotificationArea);
}
static void RefreshTraybarInTaskbar()
{
var trayInTaskbarWnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Shell_TrayWnd", null);
var trayNotifyWnd = FindWindowEx(trayInTaskbarWnd, IntPtr.Zero, "TrayNotifyWnd", null);
var sysPager = FindWindowEx(trayNotifyWnd, IntPtr.Zero, "SysPager", null);
var trayNotificationArea = FindWindowEx(sysPager, IntPtr.Zero, "ToolbarWindow32", null);
RefreshArea(trayNotificationArea);
}
static void RefreshArea(IntPtr area)
{
if (!GetClientRect(area, out var clientRect)) return;
for (int x = 0; x < clientRect.Right; x += 10)
for (int y = 0; y < clientRect.Bottom; y += 10)
SendMessage(area, WM_MOUSEMOVE, 0, (y << 16) + x);
}
I've done it by handling the ThreadException event and disposing the tray icon in that event handler.
Related
I wanna build a automatic iOS app test framework. I can record the touch event by IOHIDFamily, so any way to replay this?
I tried GSEvent like this
void sendclickevent(){
mach_port_t thePortOfApp = GSCopyPurpleNamedPort("com.fuckyou.fuck");
GSEventRecord header;
GSHandInfo click;
GSPathInfo pathInfo = {2,2,2,1,1,{50,50}, NULL};
bzero(&header, sizeof(header));
bzero(&click, sizeof(click));
header.type = kGSEventHand;
header.subtype = kGSEventSubTypeUnknown;
header.location.x = 50;
header.location.y = 50;
header.windowLocation.x = 50;
header.windowLocation.y = 50;
header.infoSize = sizeof(GSHandInfo)+sizeof(GSPathInfo);
header.timestamp = mach_absolute_time();
click.type = kGSHandInfoTypeTouchDown;
click.deltaX = 1;
click.deltaY = 1;
click.pathInfosCount = 1;
struct
{
GSEventRecord record;
GSHandInfo hand;
GSPathInfo path;
} record = {header, click, pathInfo};
GSSendEvent(&record, thePortOfApp);
}
thePortOfApp return Non-Zero. But at end of this function, such as press a button, nothing happpend. So something wrong? or I need another way to send touch event to iOS UI?
Take a look some other questions related to sending events outside of your app:
Use GSEvent to send touch event,but it's invalid
Using GraphicsServices.h/GSEvent as well as compiling CLI iPhone tools with Xcode
How to send a touch event to iPhone OS?
Simulating System Wide Touch Events on iOS
Notes
1) I believe you should send touchDown first and touchUp second to get a click.
2) Most of code which I saw on this subject used GSGetPurpleSystemAppPort() which allows to send system wide events (vs GSCopyPurpleNamedPort).
I believe GSCopyPurpleNamedPort just does usual bootstrap_look_up port. So, it will find a port, even if it's no a purple port (which is most likely true for "com.fuckyou.fuck")
How to display images fetched from url on listfield asynchronously? I am getting exception when i run the code. Here is my code. I am getting Uncaught NoClassFoundError
private Bitmap getBitmap(final String strEventCode)
{
if(hst.containsKey(strEventCode))
return (Bitmap) hst.get(strEventCode);
else
{
Thread t = new Thread(new Runnable()
{
public void run()
{
Bitmap bmp = HttpUtils.getBitmap(strHalfUrl+strEventCode+".jpg");
hst.put(strEventCode, bmp);
}
});
t.start();
}
return null;
}
I draw image using following code using ListFieldCallBack:
class ListCallBack implements ListFieldCallback
{
public void drawListRow(final ListField list, final net.rim.device.api.ui.Graphics g, final int index, final int y, final int w)
{
Event objEvent = (Event) eventData.elementAt(index);
if(list.getSelectedIndex() == index)
{
g.setColor(Color.LIGHTGRAY);
g.fillRect(0, y, getWidth(), getHeight());
}
Bitmap bmp = getBitmap(objEvent.getStrName());
if(bmp==null)
g.drawBitmap(0, y+5, loadingImage.getWidth(),loadingImage.getHeight(),loadingImage, 0, 0);
else
g.drawBitmap(0, y+5, bmp.getWidth(),bmp.getHeight(),bmp, 0, 0);
g.setColor(Color.BLACK);
int yPos = y + list.getRowHeight() - 1;
g.drawLine(0, yPos, w, yPos);
//final Bitmap b=(Bitmap)myImages.elementAt(index);
//g.drawBitmap(0, y+5, b.getWidth(),b.getHeight(),b, 0, 0);
}
public Object get(ListField list, int index)
{
return eventData.elementAt(index);
}
public int getPreferredWidth(ListField list)
{
return Display.getWidth();
}
public int indexOfList(ListField listField, String prefix, int start)
{
return eventData.indexOf(prefix,start);
}
}
I'd change a few things:
In BB, there's a max number of threads you can spawn, and it is <20 I think. You are spawning a thread per image so soon or later you'll encounter a TooManyThreadsException. You should instead have a single worker thread in your screen that downloads images. You could use a consumer-producer pattern: the user, as he scrolls down, generates image download requests (producer), and the worker thread (consumer) enqueues them to be processed. You can use a LIFO structure custom made from a Vector, and wait on it while there are no requests.
You should provide a default image to show while the real image hasn't been downloaded yet.
I'm almost sure your current code is not thread safe concerning to the hst hashtable. You should ensure your consumer is thread safe. There are plenty of examples in the net about how to do this.
Of course the worker thread should terminate when the user changes screen. In your current code, threads remain alive and will try to update the hashtable even if the user has changed to another screen.
As an optimization, if you know in advance how many threads your app usually has (without counting the image thing), and you know the max threads limit isn't going to be exceeded, you could have a thread pool of, let say, 5 threads to download images instead of a single worker thread. When all 5 threads are busy, you'll start enqueuing requests. You can also add a max time per request mechanism to prevent a thread being busy with a failed download, so instead of timing out at 2 minutes, time out at 30s and make a second request.
What is HttpUtils.getBitmap()? If it is Java code written for Java-SE, then it will not work well on a BlackBerry, as BlackBerry devices only support Java-ME, which has substantially less capability than a modern Java-SE runtime.
As for the async loading, you need to pass an event back to the UI once the fetch is complete. If you are fetching many photos at once, you will also want to add some sort of batching to that event, as sending an event for each photo can overrun the event queue on the UI app.
Hello I am trying to create a please wait screen.This screen will appear when my program requests data from web service and will hide when the process is finished.Also I want to add a time out if request process lasts longer than 90 seconds.
can anyone help or show me a guiding example about that matter.
public static void showBusyDialog() {
try
{
if (busyDialog == null) {
busyDialog = new Dialog("Please Wait", null, null, 0, Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS));
busyDialog.setEscapeEnabled(false);
}
synchronized (Application.getEventLock()) {
busyDialog.show();
}
}
catch(Exception e)
{
}
}
and my hiding code is
public static void hideBusyDialog() {
try
{
if (busyDialog == null) {
// busyDialog = new Dialog("Please wait...", null, null, 0, Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS));
busyDialog.setEscapeEnabled(false);
}
synchronized (Application.getEventLock()) {
busyDialog.close();
}
}catch(Exception e)
{
}
}
Many BlackBerry® smartphone applications need to wait for some network activity (or another blocking operation, which must process in the background), while still holding up the User Interface (UI) and displaying a progress indicator.
You can follow through this links
Links
Sample "Please Wait" screen - part 1
Sample "Please Wait" screen - part 2
Sample "Please Wait" screen - part 4
you can download simple examples for Please wait screen
PleaseWait1.zip 25 KB
PleaseWait2.zip 25 KB
PleaseWait3.zip 25 KB
Note :in case above Links not working then just follow following contents
There seem to be two common issues when programming this:
1) As applications are not allowed to block the Event Thread, how do they get the UI processing to wait?
2)How can the background Thread update the UI?
This article is intended to help with these issues and provide a fully functioning "Please Wait" sample Popup Screen. However, as there is quite a lot to explain, in this first article, we will just create a popup screen that will show itself, hold up the UI, and then remove itself once the background processing has finished. This does not give us any progress indication, nor does it let the user cancel the wait. These points will be covered in a followup article. But the code supplied with this article will be useful anyway, especially when the duration of the background processing is not known and the user may not cancel the processing.
First, we start with the background processing we need to run. While this could be anything, typically this will be network processing, like the following:
httpConn = (HttpConnection)Connector.open(_url + ";deviceside=true");
responseCode = httpConn.getResponseCode();
responseMessage = "Response Code: " + Integer.toString(responseCode);
To initiate this network processing, we have a MainScreen that contains
1) A BasicEditField that allows the entry of a URL
2) A RichTextField that should display the response code (or error message). Here are the important parts of that screen:
BasicEditField _requestedURLField = new BasicEditField("http://", "www.blackberry.com", 255, BasicEditField.FILTER_URL);
RichTextField _responseField = new RichTextField("<response code>", RichTextField.NON_FOCUSABLE);
We would like the MainScreen to be updated with the result. As noted above, background processing can't directly update the UI; UI updating code must be on the Event Thread. There are several ways to get a background process onto the Event Thread, see the related article for more. In this case, we will use the following code:
// Make things final so we can use them in the inner class
final String textString = responseMessage;
final RichTextField rtf = _resultField;
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
rtf.setText(textString);
}
});
Now we must define the PleaseWaitPopupScreen to be displayed while waiting.
To give the user something to look at while they are waiting, we have an animated .gif, which is diplayed using the code in the AnimatedGIFField (see related link). And, so the user knows what they are waiting for, the PleaseWaitPopupScreen is supplied with a String to display, as the following constructor shows:
private PleaseWaitPopupScreen(String text) {
super(new VerticalFieldManager(VerticalFieldManager.VERTICAL_SCROLL | VerticalFieldManager.VERTICAL_SCROLLBAR));
GIFEncodedImage ourAnimation = (GIFEncodedImage) GIFEncodedImage.getEncodedImageResource("cycle.agif");
_ourAnimation = new AnimatedGIFField(ourAnimation, Field.FIELD_HCENTER);
this.add(_ourAnimation);
_ourLabelField = new LabelField(text, Field.FIELD_HCENTER);
this.add(_ourLabelField);
}
PleaseWaitPopupScreen provides a method – showScreenAndWait(..) – which will create and display the Popup screen, run the Background processing, and then dismiss the Popup screen.
The final piece of the puzzle involves supplying showScreenAndWait(..) with the processing to run.
Java has the concept of a Runnable, which is an Object that contains a public void run() method that should be executed. In this case, we have the Connection code and screen update code, given above, that should be executed. So, this code is packaged up into a new Runnable Object, which is supplied to showScreenAndWait(..). And here is that method. Note how a new Thread is created and run.
public static void showScreenAndWait(final Runnable runThis, String text) {
final PleaseWaitPopupScreen thisScreen = new PleaseWaitPopupScreen(text);
Thread threadToRun = new Thread() {
public void run() {
// First, display this screen
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(thisScreen);
}
});
// Now run the code that must be executed in the Background
try {
runThis.run();
} catch (Throwable t) {
t.printStackTrace();
throw new RuntimeException("Exception detected while waiting: " + t.toString());
}
// Now dismiss this screen
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().popScreen(thisScreen);
}
});
}
};
threadToRun.start();
}
And this is the key part of the PleaseWaitPopupScreen. Note how this code will create and display a Popup screen to the user, including an animated icon, while it is running the background processing. Input from the user is blocked by the Popup screen until the processing completes. The originating screen is updated as a result of the background processing.
Download the associated .zip archive, which contains the source included in this article.
In the next article, we will extend this code to be able to handle:
a) Status updates from the Background Thread
b) "Time to go" indication
c) Being cancelled by the BlackBerry smartphone user
Just put timer after you show busy dialog.
showBusyDialog();
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
hideBusyDialog();
}
};
timer.schedule(task, 9000);
this is for time out. If the process finishes less than 90 seconds you should call
timer.cancel();
timer = null;
task = null;
I have an app that is listening in background and when the user clicks "send" it displays a dialogue. However I need to bring my app to foreground so the user answers some questions before letting the message go. but I haven't been able to do this, this is the code in my SendListener:
SendListener sl = new SendListener(){
public boolean sendMessage(Message msg){
Dialog myDialog = new Dialog(Dialog.D_OK,
"message from within SendListener",
Dialog.OK,Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),
Dialog.GLOBAL_STATUS)
{
//Override inHolster to prevent the Dialog from being dismissed
//when a user holsters their BlackBerry. This can
//cause a deadlock situation as the Messages
//application tries to save a draft of the message
//while the SendListener is waiting for the user to
//dismiss the Dialog.
public void inHolster()
{
}
};
//Obtain the application triggering the SendListener.
Application currentApp = Application.getApplication();
//Detect if the application is a UiApplication (has a GUI).
if( currentApp instanceof UiApplication )
{
//The sendMessage method is being triggered from
//within a UiApplication.
//Display the dialog using is show method.
myDialog.show();
App.requestForeground();
}
else
{
//The sendMessage method is being triggered from
// within an application (background application).
Ui.getUiEngine().pushGlobalScreen( myDialog, 1,
UiEngine.GLOBAL_MODAL );
}
return true;
}
};
store.addSendListener(sl);
App is an object I created above:
Application App = Application.getApplication();
I have also tried to invoke the App to foreground using its processID but so far no luck.
i have managed to achieve something similar to what you're describing but the difference is, my dialogs are displayed asynchronously, which might actually be easier... so in your case..
the first i could suggest you try is get the event lock before pushing the screen, ala:
synchronized(Application.getEventLock()){
final UiEngine ui = Ui.getUiEngine();
ui.pushGlobalScreen(theScreen, 1, UiEngine.GLOBAL_MODAL);
}
I would also just create a custom class of type MainScreen and push that instead of plain Dialog.
There, that's better (now with code formatting).
public class MYSendListener implements SendListener {
private UiApplication _myApp;
public MySendListener(UiApplication myApp) {
_myApp = myApp;
}
public boolean sendMessage(Message m) {
...
_myApp.requestForeground();
}
}
Cache your app instance inside your send listener when you construct it, and use that when sendMessage is fired.
Application.getApplication() only gets you the app of the calling thread.
Do anyone know maximum how many screen we can push in an UiApplication without calling popscreen() and what will be the maximum file size of each screen class.
Thanks as Regards
Mintu
UPDATE according to Marc comment
BB Documentation
Cite from How To - Manage UI interactions:
When managing your application screens on the user interface (UI) stack, do not mismatch the pushScreen() and popScreen(). When the BlackBerry smartphone user finishes interacting with the screens, pop screens off the UI stack; otherwise, the display stack continues to grow until the BlackBerry smartphone runs out of memory. You should not use more than a few modal screens at one time, because each screen uses a thread, and you should not pop the screen only once. If you pop a screen too many times, the BlackBerry smartphone trackwheel/trackball and keyboard can become unresponsive.
Cite from What Is - TooManyThreadsError:
A single application can create up to 16 threads. The total number of threads that can exist on a BlackBerry device from all applications is 128. Therefore, if an application has already created 16 threads, the 17th attempt fails and a TooManyThreadsError exception is thrown. Similarly, if there are 128 threads already created on the BlackBerry device and an application attempts to create another thread, a TooManyThreadsError exception is thrown.
Test Application
alt text http://img52.imageshack.us/img52/5937/8300testscrcount.jpg
class PushScr extends MainScreen {
static int mScrCount = 0;
Screen mContext = this;
public PushScr() {
mScrCount++;
add(new LabelField("screen count: " + mScrCount));
add(new LabelField("threads count: " + Thread.activeCount()));
add(new LabelField("memory used: "
+ Memory.getRAMStats().getAllocated()));
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(new MenuItem("push screen", 0, 0) {
public void run() {
Ui.getUiEngine().pushScreen(new PushScr());
}
});
menu.add(new MenuItem("push modal screen", 0, 0) {
public void run() {
Ui.getUiEngine().pushModalScreen(new PushScr());
}
});
if (mScrCount > 1) {
menu.add(new MenuItem("pop screen", 0, 0) {
public void run() {
Ui.getUiEngine().popScreen(mContext);
}
});
}
}
}
Conclusion
So in case of modal screens max count is 16 and common size limited by device jvm memory.
Otherwise it's all about device SRAM memory amount.