Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to properly subclass a Wnd Proc when Window words are needed ?

10 views
Skip to first unread message

Lars Erdmann

unread,
Nov 26, 2006, 6:13:55 AM11/26/06
to
Hallo,

I have written a WPS dll that creates its own view. That view contains
an MLE as its client.
That client (MLE ) is now subclassed. Problem is, I need window words to
save per-view data, for example, the somSelf ptr this view belongs to.


in short, my Wnd Proc (subclassing the MLE proc) does something like
this (disregarding error checks):

wp_Open:
...
OldProc = WinSubclassWindow(hwndMLE,MyWndProc);
WinSendMsg(hwndMLE,WM_INIT,MPFROMP(somSelf),MPFROMP(OldProc));


MyWndProc:
...
PPVERVIEW pView;
pView = (PPERVIEW)WinQueryWindowPtr(hwndMLE,QWL_USER);
...

case WM_INIT:
...
somSelf = (MyClass *)PVOIDFROMMP(mp1);
OldProc = (PFN)PVOIDFROMMP(mp2);
pView = (PPERVIEW)somSelf->wpAllocMem(sizeof(PERVIEW),NULL);
pView->somSelf = somSelf;
pView->somThis = MyClassGetData(somSelf);
pView->oldProc = OldProc;
WinSetWindowPtr(hwndMLE,QWL_USER,pView);
...

case WM_DESTROY:
if (pView)
{
somSelf = pView->somSelf;
somThis = pView->somThis;
somSelf->wpFreeMem((PBYTE)pView);
}
return (MRESULT)0;
...
default:
if (pView && pView->OldProc)
{
pView->OldProc(hwndMLE,msg,mp1,mp2);
}
else
{
WinDefWindowProc(hwndMLE,msg,mp1,mp2);
}
...

Now I have these questions:
1.) Does anyone know if the MLE original Window Procedure makes use of
QWL_USER ?
I can only say that the MLE class has created enough window word memory
to support QWL_USER index.

2.) The way this is realized does not lend itself for class
replacements. I would need to devise a strategy that saves the old value
of the QWL_USER window word and restores it when the old window proc is
called, something like this:

case WM_INIT:
...
somSelf = (MyClass *)PVOIDFROMMP(mp1);
OldProc = (PFN)PVOIDFROMMP(mp2);
pView = (PPERVIEW)somSelf->wpAllocMem(sizeof(PERVIEW),NULL);
pView->somSelf = somSelf;
pView->somThis = MyClassGetData(somSelf);
pView->oldProc = OldProc;
pView->oldWndWords = WinQueryWindowPtr(hwndMLE,QWL_USER);
WinSetWindowPtr(hwndMLE,QWL_USER,pView);
...


default:
if (pView && pView->OldProc)
{
WinSetWindowPtr(hwndMLE,QWL_USER,pView->oldWndWords);
pView->OldProc(hwndMLE,msg,mp1,mp2);
}
...

Problem is, when I restore the Window Words in "default", I loose
access/address to the ones I created in WM_INIT on the next entry into
the window proc. I would somehow need to "swap" back and forth the
original window words and the ones I created.
Does someone have a good idea how to do this ?

Ruediger Ihle

unread,
Nov 26, 2006, 10:40:55 AM11/26/06
to
On Sun, 26 Nov 2006 11:13:55 UTC, Lars Erdmann <lars.e...@arcor.de>
wrote:


> 1.) Does anyone know if the MLE original Window Procedure makes use of
> QWL_USER ?


PMREF says:

A ULONG value for applications to use is present at offset QWL_USER
in windows of the following preregistered window classes:

WC_FRAME (includes dialog windows)
WC_COMBOBOX
WC_BUTTON
WC_MENU
WC_STATIC
WC_ENTRYFIELD
WC_LISTBOX
WC_SCROLLBAR
WC_TITTLEBAR
WC_MLE
WC_SPINBUTTON
WC_CONTAINER
WC_SLIDER
WC_VALUESET
WC_NOTEBOOK

This value can be used to place application-specific data in
controls.


It is expected, that *ANY* control will allocate QWL_USER and will
keep it available for -as the name suggests- the user application
(i.e. not use it internally).


> Problem is, I need window words to save per-view data, for example,
> the somSelf ptr this view belongs to.

Doesn't each view have it's own window ? In this case, I don't see
a need for juggling with window words.


--
Ruediger "Rudi" Ihle [S&T Systemtechnik GmbH, Germany]
http://www.s-t.de
Please remove all characters left of the "R" in my email address

Alessandro

unread,
Nov 27, 2006, 2:16:31 AM11/27/06
to
In article <456976e2$0$5717$9b4e...@newsspool3.arcor-online.net>,
Lars Erdmann <lars.e...@arcor.de> wrote:

>That client (MLE ) is now subclassed. Problem is, I need window words to
>save per-view data, for example, the somSelf ptr this view belongs to.

you can use QWL_USER as this is reserved for user data
anyway if you want to store more data and do not want to allocate
a structure for that purpose (for instance because you just need 8 bytes)
you can 'superclass' the MLE control:

#define WC_EXTMLE "wc_extmle"
BOOL registerExtendedMLE(HAB hab) {
CLASSINFO ci;
if (WinQueryClassInfo(hab, WC_MLE, &ci))
{
ci.flClassStyle &= ~CS_PUBLIC; // now it will become a private class
ci.cbWindowData += 4; // add 4 bytes to the window words
if (WinRegisterClass(hab,
WC_EXTMLE, // new MLE derived class
ExtMleProc, // new MLE procedure
ci.flClassStyle, // MLE class styles less CS_PUBLIC
ci.cbWindowData) // size of window words
)
return TRUE;
}
return FALSE;
}

now you can store 4 bytes (a pointer) at QWL_USER offset and other 4 bytes
at an offset of 4. If you need more than 4 bytes just modify the above
statement:
ci.cbWindowData += 8; to add 8 bytes besides the 4 QWL_USER ones
or leave ci.cbWindowData to its value if QWL_USER is enough

in dialog scripts you can use the CONTROL statement and WC_EXTMLE as class
parameter

>case WM_DESTROY:
> if (pView)

I hope that pView is not a static variable. You should get it by
WinQueryWindowPtr() ! Static variables would be shared among all
instances of your subclassed MLEs

>default:
> if (pView && pView->OldProc)
> {
> pView->OldProc(hwndMLE,msg,mp1,mp2);
> }
> else
> {
> WinDefWindowProc(hwndMLE,msg,mp1,mp2);
> }

this other code snippets strengthens my suspect you are using a static
variable... that is wrong

I suggest you to:

- rather than subclassing each MLE instance, use superclassing (see above)
- in your DLL initialization store the original MLE procedure in a global
variable (the original MLE procedure never changes and must anyway be
shared among all instances of your class). Supposing your global variable
is a structure called global you should insert the following line to my
previous code example before "if (WinRegisterClass(hab,..." :

global.mleDefProc = ci.pfnWindowProc;
and then
default:
return global.mleDefProc(hwndMLE, msg, mp1, mp2);

of course if, for any reason, on DLL initialization MLE superclassing fails
the DLL loading should abort...

>1.) Does anyone know if the MLE original Window Procedure makes use of
>QWL_USER ?

it never does that, QWL_USER is reserved for the user

>Problem is, when I restore the Window Words in "default", I loose
>access/address to the ones I created in WM_INIT on the next entry into
>the window proc. I would somehow need to "swap" back and forth the
>original window words and the ones I created.

you do not need to do that... just use QWL_USER

P.S. I forgot to mention that in your case it is probably better to leave
the MLE unchanged...
If I did not misunderstand you, you are creating a WPS class whose instances
consists in standard PM windows containing a MLE control

If you do not need to modify the MLE behaviour you have no reason to subclass
the MLE !!!

You can build your application around a standard window or a dialog window.
Standard windows probably are easier to deal with as dialog window require
some more work to display a proper system menu icon, a menubar, etc.

In a standard window you have to register your own class for the client
(FID_CLIENT) and make it owner and parent of the MLE (see my previous post).
When registering the window class for your standard window, set the size
of window words (cbWindowData of the WinRegisterClass() prototype) to what
you need (a size of a pointer or more) and store there your data.
Offset 0 (QWL_USER) in WinQuery/Set/Window/Ptr/ULong() gives you access
to the first 4 bytes of data. You can access more data (if you reserved
that) by using the right offsets...
If you want I can send you or post here the complete code...

--
bye
Alessandro

Lars Erdmann

unread,
Dec 3, 2006, 5:50:50 PM12/3/06
to
Alessandro schrieb:

Ah, this is an interesting solution. Will keep in mind.

>>case WM_DESTROY:
>> if (pView)
>
>
> I hope that pView is not a static variable. You should get it by
> WinQueryWindowPtr() ! Static variables would be shared among all
> instances of your subclassed MLEs
>
> >default:
> > if (pView && pView->OldProc)
> > {
> > pView->OldProc(hwndMLE,msg,mp1,mp2);
> > }
> > else
> > {
> > WinDefWindowProc(hwndMLE,msg,mp1,mp2);
> > }
>
> this other code snippets strengthens my suspect you are using a static
> variable... that is wrong

No, I am using Window Words and nothing else to store per view data. The
problem I have is this (and this did not become clear, I guess):

I am writing a "scratch paper/note" WPS class called "PostWhat" derived
from WPAbstract that creates a completely new view. The new view
consists of just a frame window with frame controls, a menu and a client
of type WC_MLE.
I subclass the MLE proc (as it is the client window) and do some init
stuff (adding the view to the in-use list etc.), handle all menu
messages and do some cleanup stuff (remove the view from the in-use list
etc.).

The specific problem I have is that now, someone might want to replace
(and not just subclass) my class "PostWhat" with his own class. I want
to design the WPS class that not only the WPS class can be replaced but
also my already defined view. The new class should therefore be able to
create the view (calling wpOpen and in there, calling the parent class
that is: PostWhat) and then again subclass the client window.
But that means that the new Window Proc has to call the Window Proc of
PostWhat for all messages it does not intend to handle itself, or where
it wants the default handling of the PostWhat Window Proc + additional
handling. The Window Proc of PostWhat will in turn call the default
WC_MLE Window Proc.
The problem now is that the PostWhat Window Proc will allocate Per-View
data and put the pointer in the Window Words. But the Window Proc of the
replacement will want to have the same capability. Therefore I have to
"chain" the Window Words created for the PostWhat Window Proc and the
replacement classes Window Proc.
Note that this very same problem had to be handled by XWorkplace where
the WPFolder classes window Words had to be preserved while XFolder adds
new Window Words for its own purpose. In XWorkplace this was
(unfortunately) solved by building up a global list (eventually breaking
DSOM compatibility as global data is a big no-no for DSOM).
However I have found the solution, doing the "chaining" as described:

typedef struct _BASEWNDWORDS
{
SOMObject *somSelf;
PVOID somThis;
PFNWP thisWndProc;
PFNWP prevWndProc;
struct _BASEWNDWORDS *prevWndWords;
} BASEWNDWORDS,*PBASEWNDWORDS;


typedef struct _PERVIEW
{
USEITEM useItem;
VIEWITEM viewItem;
} PERVIEW, *PPERVIEW;


In wpOpen:
hwnd = WinCreateStdWindow(
HWND_DESKTOP,
0UL,
&ulCreateFlags,
WC_MLE,
"",
MLS_HSCROLL|MLS_VSCROLL,
g_hModule,
ID_MAIN,
&hwndClient
);

if (hwnd)
{
bRC = somSelf->wpRegisterView(hwnd,"Note View");
somSelf->wpSubClassWindow(hwndClient,WndProc);
}

In the Wnd Proc:
pBase = _PostWhat->wpclsGetPerViewData(hwndMLE,WndProc);
...
case WM_INIT:
view.useItem.type = USAGE_OPENVIEW;
view.viewItem.view = MENUID_POSTWHATVIEW;
view.viewItem.handle = hwndFrame;
pBase =
_PostWhat->wpclsAllocPerViewData(hwndMLE,msg,mp1,mp2,WndProc,&view,sizeof(view));
somSelf = (PostWhat*)_PostWhat->wpclsGetsomSelfFromPerViewData(pBase);
somThis = (PostWhatData*)_PostWhat->wpclsGetsomThisFromPerViewData(pBase);
pView = (PPERVIEW)_PostWhat->wpclsGetUserDataFromPerViewData(pBase);
...

case WM_DESTROY:
pView = (PPERVIEW)_PostWhat->wpclsGetUserDataFromPerViewData(pBase);
bRC = somSelf->wpDeleteFromObjUseList(&pView->useItem);
bRC = _PostWhat->wpclsFreePerViewData(hwndMLE,WndProc);
...

return _PostWhat->wpclsClassDefaultWindowProc(hwndMLE,msg,mp1,mp2,WndProc);

and with these additional methods:


SOM_Scope void SOMLINK wpSubClassWindow(PostWhat *somSelf, HWND hwnd,
PFNWP WndProc)
{
PFNWP oldWndProc;

PostWhatData *somThis = PostWhatGetData(somSelf);
PostWhatMethodDebug("PostWhat","SubClassWindow");

oldWndProc = WinSubclassWindow(hwnd,WndProc);
WinSendMsg(hwnd,WM_INIT,MPFROMP(somSelf),MPFROMP(oldWndProc));
return;
}

SOM_Scope PBASEWNDWORDS SOMLINK wpclsAllocPerViewData(M_PostWhat *somSelf,
HWND hwnd,
ULONG msg,
MPARAM mp1,
MPARAM mp2,
PFNWP WndProc,
PVOID pUserData,
ULONG ulLen)
{
PBASEWNDWORDS pBase;
PostWhat *objInst = (PostWhat *)PVOIDFROMMP(mp1);
PFNWP oldWndProc = (PFNWP)PVOIDFROMMP(mp2);
BOOL fRC;

/* M_PostWhatData *somThis = M_PostWhatGetData(somSelf); */
M_PostWhatMethodDebug("M_PostWhat","AllocPerViewData");

if (msg != WM_INIT || !somIsObj(objInst) || !oldWndProc)
{
return (PBASEWNDWORDS)NULL;
}

pBase =
(PBASEWNDWORDS)objInst->wpAllocMem(ulLen+sizeof(BASEWNDWORDS),NULL);
if (pBase)
{
pBase->somSelf = (SOMObject *)objInst;
pBase->somThis = (PVOID)somDataResolve((SOMObject
*)objInst,somSelf->somGetInstanceToken());
pBase->thisWndProc = WndProc;
pBase->prevWndProc = oldWndProc;
pBase->prevWndWords =
(PBASEWNDWORDS)WinQueryWindowPtr(hwnd,QWL_USER);
if (pUserData && ulLen)
{
memcpy(pBase+1,pUserData,ulLen);
}
WinSetWindowPtr(hwnd,QWL_USER,pBase);
}
return pBase;
}


SOM_Scope PBASEWNDWORDS SOMLINK wpclsGetPerViewData(M_PostWhat *somSelf,
HWND hwnd, PFNWP WndProc)
{
PBASEWNDWORDS pBase;

/* M_PostWhatData *somThis = M_PostWhatGetData(somSelf); */
M_PostWhatMethodDebug("M_PostWhat","GetPerViewData");
pBase = (PBASEWNDWORDS)WinQueryWindowPtr(hwnd,QWL_USER);
while (pBase && pBase->thisWndProc != WndProc)
{
pBase = pBase->prevWndWords;
}
return pBase;
}

SOM_Scope SOMObject* SOMLINK wpclsGetsomSelfFromPerViewData(M_PostWhat
*somSelf,
PBASEWNDWORDS
pBase)
{
/* M_PostWhatData *somThis = M_PostWhatGetData(somSelf); */
M_PostWhatMethodDebug("M_PostWhat","GetsomSelfFromPerViewData");
if (pBase)
{
return pBase->somSelf;
}
else
{
return (SOMObject *)NULL;
}
}

SOM_Scope PVOID SOMLINK wpclsGetsomThisFromPerViewData(M_PostWhat *somSelf,
PBASEWNDWORDS pBase)
{
/* M_PostWhatData *somThis = M_PostWhatGetData(somSelf); */
M_PostWhatMethodDebug("M_PostWhat","GetsomThisFromPerViewData");
if (pBase)
{
return pBase->somThis;
}
else
{
return NULL;
}
}

SOM_Scope PVOID SOMLINK wpclsGetUserDataFromPerViewData(M_PostWhat
*somSelf,
PBASEWNDWORDS pBase)
{
/* M_PostWhatData *somThis = M_PostWhatGetData(somSelf); */
M_PostWhatMethodDebug("M_PostWhat","GetUserDataFromPerViewData");
if(pBase)
{
return (pBase+1);
}
else
{
return NULL;
}
}


SOM_Scope BOOL SOMLINK wpclsFreePerViewData(M_PostWhat *somSelf,
HWND hwnd, PFNWP WndProc)
{
PBASEWNDWORDS pBase,pTemp;
PostWhat *objInst;

/* M_PostWhatData *somThis = M_PostWhatGetData(somSelf); */
M_PostWhatMethodDebug("M_PostWhat","FreePerViewData");

pBase = (PBASEWNDWORDS)WinQueryWindowPtr(hwnd,QWL_USER);

/*
if our Window Words are the first ones in the chain,
make sure that we replace the Window Word pointer to
point to the next element in the chain as our Window Words
will be removed, see end of routine
*/
if (pBase && pBase->thisWndProc == WndProc)
{
WinSetWindowPtr(hwnd,QWL_USER,pBase->prevWndWords);
objInst = (PostWhat *)pBase->somSelf;
objInst->wpFreeMem((PBYTE)pBase);
return TRUE;
}
else
{

/*
cycle until we are FOLLOWED by the Window Word block that
is to be removed
(identified by a matching Window Procedure address)
*/
pTemp = NULL;
while(pBase && pBase->thisWndProc != WndProc)
{
pTemp = pBase;
pBase = pBase->prevWndWords;
}
pBase = pTemp;

/*
now that we have found the preceding element, unchain our
element
and make sure we close the chain so that the previous ptr
of the preceding
elements points to where our previous ptr pointed to
*/
if (pBase && pBase->prevWndWords)
{
pTemp = pBase->prevWndWords;
pBase->prevWndWords = pBase->prevWndWords->prevWndWords;
pBase = pTemp;
}

if (pBase)
{
objInst = (PostWhat *)pBase->somSelf;
objInst->wpFreeMem((PBYTE)pBase);
return TRUE;
}
else
{
return FALSE;
}
}
}

SOM_Scope MRESULT SOMLINK wpclsClassDefaultWindowProc(M_PostWhat *somSelf,
HWND hwnd,
ULONG msg,
MPARAM mp1,
MPARAM mp2,
PFNWP WndProc)
{
PBASEWNDWORDS pBase;
MRESULT mres;

/* M_PostWhatData *somThis = M_PostWhatGetData(somSelf); */
M_PostWhatMethodDebug("M_PostWhat","ClassDefaultWindowProc");

pBase = (PBASEWNDWORDS)WinQueryWindowPtr(hwnd,QWL_USER);
while(pBase && pBase->thisWndProc != WndProc)
{
pBase = pBase->prevWndWords;
}

if (pBase && pBase->prevWndProc)
{
mres = pBase->prevWndProc(hwnd,msg,mp1,mp2);
}
else
{
mres = (MRESULT)0;
}
return mres;
}

I have verified that it indeed works by writing a test class that
replaces PostWhat view class and in turn subclasses the PostWhat Window
Proc (by using wpSubClassWindow) in its own processing of wpOpen.

Nevertheless your superclassing approach is really interesting. But it
wouldn't work in this case as the window class has to remain the same if
the replacement class intends to replace an already existing view.


Lars

Ruediger Ihle

unread,
Dec 4, 2006, 10:28:11 AM12/4/06
to
On Sun, 3 Dec 2006 22:50:50 UTC, Lars Erdmann <lars.e...@arcor.de>
wrote:

> Therefore I have to "chain" the Window Words created for the PostWhat


> Window Proc and the replacement classes Window Proc.
>

>...


>
> Note that this very same problem had to be handled by XWorkplace where
> the WPFolder classes window Words had to be preserved while XFolder adds
> new Window Words for its own purpose. In XWorkplace this was
> (unfortunately) solved by building up a global list (eventually breaking
> DSOM compatibility as global data is a big no-no for DSOM).


But wouldn't that require, that the original WPFolder class had
to use your approach as well ? If so, it's not really a solution
for XWorkplace.

Lars Erdmann

unread,
Dec 4, 2006, 7:55:29 PM12/4/06
to
Ruediger Ihle schrieb:

> On Sun, 3 Dec 2006 22:50:50 UTC, Lars Erdmann <lars.e...@arcor.de>
> wrote:
>
>
>>Therefore I have to "chain" the Window Words created for the PostWhat
>>Window Proc and the replacement classes Window Proc.
>>
>>...
>>
>>Note that this very same problem had to be handled by XWorkplace where
>>the WPFolder classes window Words had to be preserved while XFolder adds
>>new Window Words for its own purpose. In XWorkplace this was
>>(unfortunately) solved by building up a global list (eventually breaking
>>DSOM compatibility as global data is a big no-no for DSOM).
>
>
>
> But wouldn't that require, that the original WPFolder class had
> to use your approach as well ? If so, it's not really a solution
> for XWorkplace.

In general you are right. But if you restrict the "class replacement
depth" to 1 (which is a good practical limit) I think you could find
a(nother) solution involving WinQueryClassName/WinQueryClassInfo and
maybe a "magic word" to safely identify your block of window words to
get to the originally active Window Procedure (before any Window
subclassing at all) when necessary.
In my case the specific problem is that wpclsClassDefaultWindowProc is
called from the 1. class replacement as well as from the 2. class
replacement (and so on) and, even worse, the Window Proc of 1.
replacement class calls into the Window Proc of 2. replacement class and
vice versa. It took me a few hours of WPS debugging and stack tracing
until I finally understood what was going on in detail.
In fact I also had to change my code to use
WinQueryClassName/WinQueryClassInfo to catch an error case where the 1.
replacement class does not successfully allocate the window words (and
therefore the window words continue to contain a NULL pointer as that is
the value an MLE puts at offset QWL_USER).
I then call WinDestroyWindow to suppress the creation of the window
(because it could not be correctly managed). But WinDestroyWindow enters
the window processing again and this case has to be handled gracefully:

SOM_Scope MRESULT SOMLINK wpclsClassDefaultWindowProc(M_PostWhat *somSelf,
HWND hwnd,
ULONG msg,
MPARAM mp1,
MPARAM mp2,
PFNWP WndProc)
{

PBASEWNDWORDS pBase,pTemp;
MRESULT mres;

/* M_PostWhatData *somThis = M_PostWhatGetData(somSelf); */
M_PostWhatMethodDebug("M_PostWhat","ClassDefaultWindowProc");

pBase = pTemp = (PBASEWNDWORDS)WinQueryWindowPtr(hwnd,QWL_USER);
while(pTemp && pTemp->thisWndProc != WndProc)
{
pTemp = pTemp->prevWndWords;
}

if (pTemp && pTemp->prevWndProc)
{
mres = pTemp->prevWndProc(hwnd,msg,mp1,mp2);
}
/*
we have to catch the case that we have to call the old
Wnd Procedure even when new Window Words could not be allocated
this will happen if the Window is destroyed because of failure
of wpclsAllocPerViewData and subsequent calling of WinDestroyWindow
*/
else if (pBase && pBase->thisWndProc)
{
mres = pBase->thisWndProc(hwnd,msg,mp1,mp2);
}
/*
finally, if we don't succeed in accessing any Window word
block at all (failure of 1. replacement class), let's try to
call the original Window procedure
that was active before any subclassing was done at all
*/
else
{
CHAR szClsName[256];
CLASSINFO clsInfo;
ULONG ulLen;
HAB hab;
BOOL fRC;

memset(&clsInfo,0,sizeof(clsInfo));
hab = WinQueryAnchorBlock(hwnd);
ulLen =
WinQueryClassName(hwnd,sizeof(szClsName),szClsName);
fRC =
WinQueryClassInfo(hab,szClsName,&clsInfo);
if (fRC)
{
mres = clsInfo.pfnWindowProc(hwnd,msg,mp1,mp2);


}
else
{
mres = (MRESULT)0;
}
}
return mres;
}

But I frankly admit that Window Procedures do not lend themselves well
for a complete WPS class replacement (including the
replacement/subclassing of a view created by the replaced class).
Maybe that's the reason why WPFolder/WPDataFile etc. do not provide any
class methods to do so and the necessary rules what method is to be
called when.

Lars

Alessandro

unread,
Dec 4, 2006, 12:04:22 AM12/4/06
to
In article <457354be$0$18834$9b4e...@newsspool4.arcor-online.net>,
Lars Erdmann <lars.e...@arcor.de> wrote:

>The specific problem I have is that now, someone might want to replace
>(and not just subclass) my class "PostWhat" with his own class. I want
>to design the WPS class that not only the WPS class can be replaced but
>also my already defined view. The new class should therefore be able to
>create the view (calling wpOpen and in there, calling the parent class
>that is: PostWhat) and then again subclass the client window.

In this case I think it might be more appropriate to separate the application
features from the MLE ones by registering your own client class and using
an unsubclassed (i.e. original) MLE as child of your client (as I suggested
in my previous post).

That method would make subclassing your WPS class easier.
For instance a subclass might need to use a more advanced multi-line-edit
control to display text with style attributes. In such case it would be
necessary to just replace the mle with another window class and modify
the client class procedure.

--
bye
Alessandro

Ruediger Ihle

unread,
Dec 5, 2006, 1:19:26 PM12/5/06
to
On Tue, 5 Dec 2006 00:55:29 UTC, Lars Erdmann <lars.e...@arcor.de>
wrote:

> But I frankly admit that Window Procedures do not lend themselves


> well for a complete WPS class replacement (including the
> replacement/subclassing of a view created by the replaced class).


Probably yes. OTOH, it seems to me that the question should not be
"How to properly subclass a Wnd Proc when Window words are needed"
but how to access/add additional per-view data in an derived view
of an object. When thinking about this: wouldn't it be possible to
create a custom "USEITEM" ?


Anyway, I seem to remember that you were working on the FAT32 code.
Is there anything new ? The IFS badly needs some optimizations...

Lars Erdmann

unread,
Dec 6, 2006, 2:45:10 PM12/6/06
to
Ruediger Ihle schrieb:

> On Tue, 5 Dec 2006 00:55:29 UTC, Lars Erdmann <lars.e...@arcor.de>
> wrote:
>
>
>>But I frankly admit that Window Procedures do not lend themselves
>>well for a complete WPS class replacement (including the
>>replacement/subclassing of a view created by the replaced class).
>
>
>
> Probably yes. OTOH, it seems to me that the question should not be
> "How to properly subclass a Wnd Proc when Window words are needed"
> but how to access/add additional per-view data in an derived view
> of an object. When thinking about this: wouldn't it be possible to
> create a custom "USEITEM" ?
I thought about this. Problem is I then have a "circular problem".
I need the somSelf pointer to access the USEITEM structure
(wpFindUseItem,wpFindViewItem) but then the only place to save and
access the somSelf pointer from within a Window Proc is via the
USEITEM/VIEWITEM structure ...

> Anyway, I seem to remember that you were working on the FAT32 code.
> Is there anything new ? The IFS badly needs some optimizations...

1.) my old laptop has finally quit service. And it will be difficult to
convice my wife to buy a laptop only so that I can debug.
2.) The cache handling code in FAT32 does not well support flushing
large amounts of sectors from cache to disk (when large files are loaded
that by far overflow the cache, the entire contents of the cache have to
be flushed quickly). You need disk-contiguous sectors for efficient
transfer to disk, no matter if you use the Strat2 Entry point or
FSH_DOVOLIO.
Strat2 will better the situation as it allows linear discontigous memory
but currently the cache sectors are not sorted or linked according to
sector number. My feeling is, the cache handling will need substantial
changes.

Lars

Ilya Zakharevich

unread,
Dec 6, 2006, 5:19:40 PM12/6/06
to
[A complimentary Cc of this posting was sent to
Lars Erdmann
<lars.e...@arcor.de>], who wrote in article <45771dc2$0$18847$9b4e...@newsspool4.arcor-online.net>:

> 2.) The cache handling code in FAT32 does not well support flushing
> large amounts of sectors from cache to disk (when large files are loaded
> that by far overflow the cache, the entire contents of the cache have to
> be flushed quickly). You need disk-contiguous sectors for efficient
> transfer to disk, no matter if you use the Strat2 Entry point or
> FSH_DOVOLIO.

> Strat2 will better the situation as it allows linear discontigous memory
> but currently the cache sectors are not sorted or linked according to
> sector number.

I do not see why this should be a problem, if you *know* you want to
flush a lot of data. Consider the following scenario:

if number of sectors to flush is more than a certain threshold
(e.g., 2% of the total number?), collect all of the pending sectors
into a flat list, qsort the list, and choose contiguous chunks from
the resulting list.

Puzzled,
Ilya

Ruediger Ihle

unread,
Dec 7, 2006, 1:43:44 AM12/7/06
to
On Wed, 6 Dec 2006 19:45:10 UTC, Lars Erdmann <lars.e...@arcor.de>
wrote:

> but then the only place to save and access the

> somSelf pointer from within a Window Proc is via the
> USEITEM/VIEWITEM structure ...

What about QWL_USER ?


> My feeling is, the cache handling will need substantial
> changes.

IMHO, the whole thing needs substantial changes. I had
hoped, that you would jump in. OTOH, I have added larger
harddrives to my computers and created additional data
partions. IOW, I have given up to use the data exchange
partiton with Windows for regular storage, since the
performance/CPU-usage of FAT32.IFS is inacceptable. And
I live with the CACHEF32-memorial-crash on each (auto-)
CHKDSK at bootup.

Lars Erdmann

unread,
Dec 9, 2006, 1:18:30 PM12/9/06
to
Ilya Zakharevich schrieb:

Great, you do it then. Code is on netlabs SVN.

Lars

Ilya Zakharevich

unread,
Dec 9, 2006, 7:08:13 PM12/9/06
to
[A complimentary Cc of this posting was sent to
Lars Erdmann
<lars.e...@arcor.de>], who wrote in article <457afdeb$0$30321$9b4e...@newsspool1.arcor-online.net>:

> Great, you do it then. Code is on netlabs SVN.

"Then"?

Ilya

0 new messages