• Announcements

    • Reminder - MoDaCo position on illegal content

      ILLEGAL CONTENT I'd like to just reaffirm MoDaCo's position regarding piracy and illegal content in the light of some recent questions / postings. Posts will be censored by myself or my moderation team if the contain or link to: Illegal / pirated / cracked software or sites that host such software
      Nintendo emulators / ROMs or sites hosting them (in light of Nintendo's legal stance)


      CUSTOM ROMS

      You may discuss and post links to custom device ROMs on MoDaCo, provided the following rules are adhered to: ROMs must not be hosted directly in topic via the MoDaCo attachment system
      ROMs must not contain any illegal 3rd party software (this includes trial versions included without permission)
      ROMs must give full credit to the original author
      This decision has been taken in light of the huge amount of interest in this area of device customisation within the community, and member feedback! Please note that custom ROM discussion should be kept in specific device sub-areas, (e.g. Kaiser.MoDaCo.com for Kaiser based devices). ISSUES If you have any issues with this policy, please contact me directly via PM. P
    • Support MoDaCo by signing up to a MoDaCo Silver or Gold membership

      To sign up to an annual MoDaCo Silver subscription which will eliminate all ads from the site (as well as giving you access to the MoDaCo Online Kitchens for Android) for only £9.99 using PayPal, Credit or Debit Card, ensure you are logged in to the site, and then click the link below, which will take you directly to the subscription store! You can also sign up to an annual MoDaCo Gold subscription for £29.99, which adds the benefits listed below! PURCHASE A MODACO SUBSCRIPTION - FREE Titanium Backup Mobile for Android worth $5.99! - FREE 1 year PrivateInternetAccess.com worth $39.95! - FREE 1 year LastPass Premium worth $12! - FREE CalcConvert for Pocket PC from Binaryfish worth $17.95! - FREE Calendar Bar for Pocket PC from OmegaOne worth $9.99! - FREE CamerAware for Pocket PC and Smartphone from MoDaCo worth £19.99 / $30! - FREE Chronos for Pocket PC from ActiveKitten worth $14.95! - FREE CodeWallet Pro for Smartphone and Pocket PC from DeveloperOne worth up to $24.95! - FREE Concentrix for Pocket PC from eSoft Interactive worth $9.95! - FREE FlexMail for Pocket PC and Smartphone from WebIS worth up to $59.90! - FREE FTouchSL for Pocket PC from Vekoff s.r.o. worth 10 euro / $12.50! - FREE Jewel Challenge for Pocket PC from eSoft Interactive worth $9.95! - FREE John Cody's Alerts Pro for Smartphone from Omnisoft worth $14.95! - FREE LingvoSoft Talking Dictionary 2008 English <-> Dutch for Pocket PC from Lingvosoft worth $49.95! - FREE LingvoSoft Talking Dictionary 2008 English <-> French for Pocket PC from Lingvosoft worth $49.95! - FREE LingvoSoft Talking Dictionary 2008 English <-> German for Pocket PC from Lingvosoft worth $49.95! - FREE LingvoSoft Talking Dictionary 2008 English <-> Italian for Pocket PC from Lingvosoft worth $49.95! - FREE LingvoSoft Talking Dictionary 2008 English <-> Spanish for Pocket PC from Lingvosoft worth $49.95! - FREE LingvoSoft Dictionary English <-> Dutch for Smartphone from Lingvosoft worth $49.95! - FREE LingvoSoft Dictionary English <-> French for Smartphone from Lingvosoft worth $49.95! - FREE LingvoSoft Dictionary English <-> German for Smartphone from Lingvosoft worth $49.95! - FREE LingvoSoft Dictionary English <-> Russian for Smartphone from Lingvosoft worth $49.95! - FREE LingvoSoft Dictionary English <-> Turkish for Smartphone from Lingvosoft worth $49.95! - FREE Note2Self for Pocket PC and Smartphone from WebIS worth up to $19.90! - FREE Opera 8.60 for Pocket PC and Smartphone from Opera Software worth up to $48! - FREE Pocket Informant for Pocket PC and Smartphone from WebIS worth up to $59.90! - FREE Pocket Launcher for Pocket PC and Smartphone from Conduits worth $9.95! - FREE PTab for Pocket PC and Smartphone from z4soft worth up to $60! - FREE Resco Explorer for Pocket PC and Smartphone from Resco worth up to $49.90! - FREE Safemode for Pocket PC from monocube worth $12.95 - FREE SplashPhoto for Pocket PC and Smartphone from SplashData worth up to $59.90! - FREE Sprite Backup for Pocket PC and Smartphone from Sprite Software worth $29.95! - FREE Teksoft Glyphs UI for Pocket PC and Smartphone from Teksoft €9.95! - FREE Teksoft HeadsetRemote for Pocket PC and Smartphone from Teksoft €4.95! - FREE Traffic Jam for Pocket PC from eSoft Interactive worth $9.95! - FREE unlock (1 per year) from imei-check.co.uk - DISCOUNT of 10% at MoDaCo FairDeal - DISCOUNT of 10% at Semsons.com - FORUM - AD FREE SITE - FORUM - custom rank / title - FORUM - double competition entries - FORUM - double post attachment space - FORUM - no search flood control - FORUM - priority event registration - FORUM - triple PM space
    • Reminder: Selling items on the forum directly is not allowed

      Please note that selling items on the forum directly is not allowed by the forum rules. There is a forum for eBay auctions whereby you can list the items on eBay and link to them there. This is the ONLY forum for this type of activity. You may also advertise links to the eBay forum in your signature. Please note that selling directly in contravention of these rules will result in a warning / suspensions / ban.
Sign in to follow this  
Followers 0

Using the Windows Timer in plugins

17 posts in this topic

Posted · Report post

I've been writing a plugin in Embedded Visual C++ and have most of the code working now but have come accross a problem trying to use the Windows Timer. Although I can set a timer up (using SetTimer), because I don't have a window handle I never get any WM_TIMER messages posted to my app. Using timers in normal Windows programs has never caused a problem for me in the past because I DO have a handle to a Window.

Does anyone know how to use timers like this in plugins?

Thanks in advance,

-Mark.

0

Share this post


Link to post
Share on other sites

Posted · Report post

Even though you don't have a window, you still have to process a message loop to get Windows timers to work.

So, while you'd think something like this would work:

hevent = CreateEvent(NULL, FALSE, FALSE, NULL);

ntimer = SetTimer(NULL, 0, dwInterval, MyTimerProc);



WaitForSingleObject(hevent, INFINITE);[/code] it won't. Your little TimerProc will never see a timer message and you'll be a sad panda. Instead, you have to process messages for your thread like so:
[code]ntimer = SetTimer(NULL, 0, dwInterval, MyTimerProc);



for (;;)

{

  MSG msg;



  GetMessage(&msg, NULL, 0, 0);

  DispatchMessage(&msg);

}

(of course, you'll need to have some sort of way to exit out of that loop, but that's an exercise left to the reader.)

The Remarks section of SetTimer tries to explain this:

An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.  

Good luck!

0

Share this post


Link to post
Share on other sites

Posted · Report post

Cheers for the advice. Still can't get it working tho. I've tried creating a thread (using CreateThread) to put a message loop in but it doesn't seem to work. The first time I ran it, the thread ran as expected but I can't get it to work anymore despite the fact that the code hasn't changed!

I'm getting pretty close to giving up now, I've spent four days trying to figure this out! I'm surprised that no-one else seems to be having these problems, it seems like quite a basic (although essential) thing I'm trying to do.

Any idea how other plugins update themselves (they all must do it somehow)? If only I could find some source code...

0

Share this post


Link to post
Share on other sites

Posted · Report post

Well, here's code for a fully functioning program (the lines above plus a WinMain to wrap it) that makes my phone beep merrily away.

Alternatively, there's no reason you can't create a little (hidden) window to be a message receptacle -- that's a perfectly reasonable and valid Windows programming technique.

timerproc.cpp

0

Share this post


Link to post
Share on other sites

Posted · Report post

Well, here's code for a fully functioning program (the lines above plus a WinMain to wrap it) that makes my phone beep merrily away.

Alternatively, there's no reason you can't create a little (hidden) window to be a message receptacle -- that's a perfectly reasonable and valid Windows programming technique.

I have already done that for ppc, you can create a hidden window, save its handle in a static variable or function, and use it anytime you need in your application.

DM

0

Share this post


Link to post
Share on other sites

Posted · Report post

Cheers for the advice, I've now managed to do it in a similar way by creating a thread shortly after initialising my DLL, which handles my messages for me - works a treat ;) I actually tried using this approach a while ago but couldn't get it working - after hours of playing around with it I figured out that you can't create a thread from a dll's initialise function which is what I was trying to do - weird :shock:

Thanks again,

-Mark.

0

Share this post


Link to post
Share on other sites

Posted · Report post

oh theres a better way with plugins, they follow there own unique architecture.

Theres a function called setSingleShotTimer (in IHomePluginEnvironment), anyway in general timers are really bad in plugins as they eat at the battery life. Neil Enns and MS did a web cast thingy ma-bob.

Anyway if you are checking to see if data has changed somewhere else there is a much easier way to do it. Get the app to tell the plugin when its changed by sending a

SHonPluginDataChante (const CLSID * pclsidPlugin);

#include

(aygshell.lib too in your settings).

If you have # defined your GUID the you can just pass it the address of the plugin.

Your plugin then needs to handle datachange by invalidating itself so it repaints. Its sadly not documented in the 02 SDK but it was covered in the MS webcast. Its well worth watching.

0

Share this post


Link to post
Share on other sites

Posted · Report post

Thanks for that, interesting function name, wonder what that means... Strange this stuff isn't documented, makes it tricky to find out about it really! Anyway, like I say I've done it a different way now (as a thread) which I really like cus it keeps it all very tidy in a single application :) but this is something to think about in the future, especially if I do ever need an app and plugin running side by side.

Incidentally, people keep telling me that timers kill the battery (I'm not saying they're wrong, it even says it in the documentation so there's presumably some truth in it), but does anybody know why? My current plugin has a 5 second timer and it seems to make no difference to battery life at all - it's still as bad as it ever was! All my plugin does when it gets a timer event is check for changes - it only actually invalidates the plugin if a change has occured - probably about every 15 mins or so. How can performing such a tiny set of instructions with such a powerful but efficient processor cause extra energy consumption? A bit off topic but I'd still be very interested to know :wink:

Anyway, thanks again.

0

Share this post


Link to post
Share on other sites

Posted · Report post

SHonPluginDataChante (const CLSID * pclsidPlugin);

Aha, just realised you meant SHOnPluginDataChange(). Makes more sense now!

0

Share this post


Link to post
Share on other sites

Posted · Report post

I have a question I think you guys could help me with. You might have seen my pitiful efforts at plug-in writing elsewhere on this forum :lol:

Anyway, I've got Initialize code to parse the XML parameters receieved from the home XML file, but I can't seem to store these values. It looks something like this:

#plugin.cpp

int value = 10;

HRESULT Plugin::OnEvent(PluginEvent){

...

CASE WM_ACTION:

print(value); // pseudocode

}

HRESULT Plugin:Initialize(HPLUGIN, IXMLDOMNODE*,IXMLDOMNODE*)

{

value = 5;

print(value); // pseudocode

}

I know that the Initialize code is being called, because my print(value) command returns 5. But when I click the plugin, print(value) still returns 10.

Can anyone offer any suggestions as to why this is, and what I should be doing? I assume it's something to do with my use of a global variable... maybe...?

0

Share this post


Link to post
Share on other sites

Posted · Report post

Ahh, the old Initialize function! I never tire of trying to figure this one out! I think I know what the problem is, but unfortunately, I don't have a solution :lol:

Firstly, your code looks right to me, and if plugins worked in the way you'd expect then I'd expect your code to work. However, unfortunately plugins seem to work in rather more mysterious ways:

As far as I can tell, Windows treats the initialize function as a static function which it calls purely to initialize the plugin. Once this has been called, it ceases to use this instance of the plugin and creates a new instance which is the one you actually see on your screen (and the best part is that for this new instance, the initialize function does not get called again!) Verify this by outputting the value of 'this' - first from Initialize(), and then from any other function; it will be a different value. The effect of this is that if you're using global variables in the way you described, when you print the value of your variable from Initialize(), it will be using a different instance of the variable to the other functions in your class.

Normally this isn't a problem because you can do any initialization elsewhere; I usually create an m_bInitialized flag which is set to false in the constructor, then initialization is done at the start of the OnEvent function since this will be reached before anything else, then the flag is set to true so the plugin doesn't get initialized again.

My problem is, and going on what you said about parsing XML, I suspect you're having the same problem, the only place you can get at your XML is in the Initialize function. Like I say tho, at this point I'm afraid I don't have a solution!

Anyway, hopefully this post will help explain the problem (assuming that I'm right about this of course,) so in light of this you might be able to think of a solution. The best idea I've come up with so far is to store the information you need from Initialize in some sort of persistent memory store - if worst comes to worst it could be stored in the registry or in a file which both parts of the plugin can get at, but this is a bit of a dirty hack!

If you think of a solution to this, please let me know because I'm trying to solve this problem too.

Hope this helps and, more importantly, makes some sense (it was a struggle to try to put this in to plain English!)

0

Share this post


Link to post
Share on other sites

Posted · Report post

ok guys,

plugins are strange creatures and live a strange life, they are in fact loaded twice before paint is ever called , and as you have both discovered the paint and the action are the easy part :lol: now comes the real *fun* part making it configurable

Plugins handle

PE_DATACHANGE

(these normally call Invalidate)

PE_ACTION

PE_PAINT

PE_TIMER (via SetSingleShotTimer)

for PluginEvent rather than WindowEvents etc

there are loads more look for plugin events in the SDK, but don't go trying to capture the up or down keys as thats real hackery.

You are correct that initialize is the only oppurtunity to parse the xml, this is done outside as it were of an actual real instance of your plugin in that it runs outside of home.exe. The first time your plugin loads its parse the xml, this is because the xml parser is very prome to memory leaks so if it happened inside hom.exe as it were then it would bomb your phone so its a helper process on "cold boot" or first load.

then you need to implement

IPersistStream::Save

where you save the xml that you have just parsed and other things of interest.

The next time your plugin loads it calls

IPersistStream::Load

this loads all the information that you have parsed in intialize and stored in save ............................................ and sets the plugin state (its created in the meantime and loaded whrn the home.exe state is streamed in as it were)

To get the idea of what happening think of a "Helper function" thats sits outside home.exe in this "function" the process is

1. read in xml file

2. Create Plugin

3. Initialize plugin

4. Stream Out/ Save plugin

5. Destroy plugin

The process that occurs within home.exe is different as the plugin reads itself rahter than initialze itself. THis is done so that hom.exe remains responsive (and running) during setting changes.

1. Stream in home.exe state

2. create plugins

3. stream in plugin state

4. handle actions

Once you have all that mastered the next joy is attempting to get the homescreen colours as 2002 doesn't offer the new getcolor function and don't bother going looking for them in syscolor either as the 4 plugin colours aren't saved there either ;)

This has to be saved out into intialize to as there are no apis for it, so you need to know how to ascretain the appropriate colour scheme get the colours out and convert them to syscolors etc.

Plugins are tricky and not the simplest beast to handle or control and memory leaks are a *real* headache you must capture even the small ones as they mount up over a power cycle as it were (home.exe doesn't die till you turn it off, or load a new homescreen) .....

Then I guess its the bgimage support in the format tags and all the default font settings etc as well as those from within your plugin (padding, alignment etc).

oh how we *wish* for a getFormat ............

I hope this has helped and given you an idea on where to start.

I can't help but think the real innovation with a plugin is actullay building one that use the homescreen colours rather than those set in the format tag on a 2002 device.

0

Share this post


Link to post
Share on other sites

Posted · Report post

Excellent, thanks a lot for that! Glad to see I was on the right lines with what I'd managed to figure out, even managed to use the word persistent myself :lol: Think I've managed to figure out most of the other stuff already (including getting the colours - went through that a while ago and managed to find them lurking in the registry.) In fact, I think the only thing I have left to figure out now is how to enumerate stuff like COLOR_HOMETEXT to its actual colour value. Something for another day I imagine...

How come you know exactly how these plugins work (the exact process they go through)? I managed to figure a lot of it out by trawling through the code and putting debug out etc. but don't think I'd have managed to figure all that out!

Thanks again, you've been fantastically helpful!

0

Share this post


Link to post
Share on other sites

Posted · Report post

I second that, many thanks for your help. FWIW I also found some useful stuff on . Having added a print(value) to the Save method I can see it is being called with the global variables I set in Initialize, still visible.

I was going to ask for tips on IPersistStream, but then I found >>this<< url. Could someone cast their eye over it briefly and indicate whether the first long code example is the *sort of thing* I should use to save my variables?

If not thanks for all the help anyway, guys :lol:

0

Share this post


Link to post
Share on other sites

Posted · Report post

yeah the StinkerColor look up provided by Orange rocks, see they are nice people really and they do try to help developers.

I bet they broke there balls doing it the real way and thought ... bless ....... third party developers we'll give em a lookup table so they don't die too young. Thing is though thats only available on an orange phone as it gets set by their shortcut plugin. (I figured that out too)

In terms of figurig it out I'm a tenatious lady who like to know how the black box works (its cos chix dig unix) and XML parsing is dodgy at the best of times let alone in a process that runs continuosly, and lets just say I have some experience with plugins.

0

Share this post


Link to post
Share on other sites

Posted · Report post

Yeah the url for the persist stuff is alson the right lines, where plugins differ again is that you need to call Invalidate if the stream becomes dirty (its changed so you need to do lots of exciting stuff like re save and paint yourself).

You need to keep paint really fast too, so think about how you handle you data carefully too.

0

Share this post


Link to post
Share on other sites

Posted · Report post

Two part question.

1) How do I call SHOnPluginDataChange from a C# application.

2) Where is the list of Links that are displayed in the MRU plug in

stored.

I would like to re order the MRU links and refresh the plugin using a

C# program.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

MoDaCo is part of the MoDaCo.network, © Paul O'Brien 2002-2015. MoDaCo uses IntelliTxt technology.