Discussion:
Shell Refresh - revisited
(too old to reply)
Chuck Chopp
2005-03-29 22:33:11 UTC
Permalink
I've only had limited success in my attempts to force the shell to refresh
itself after changes have been made to the underlying data that my NSE
displays as the first level of folders under the root of my NSE. If I
manually hit F5, the shell refreshes the shell folder view on the right hand
side of the Windows Explorer window. If I collapse the NSE's root folder
tree and hit F5 and then re-expand it, then the shell folder tree list gets
updated as well, such as when data representing a folder has been deleted
and the folder needs to be removed. Please note that the modifications
being made to the data are beyond my control, they don't happen within the
NSE itself and I don't have any possible way to send specific
SHChangeNotify() messages specifying exact PIDL values for virtual folders
that have been added or removed as a result of the data modification. I
have a series of manual steps I can perform that definitely result in a
refresh of the information, but converting those manual steps into program
code is presenting me with some difficulties.

How do you programmatically initiate a refresh as if the F5 key had been hit
in the Windows Explorer? Is it a particular call to SHChangeNotify() or
SendMessage() that does the job?


TIA,

Chuck
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Rhett Gong [MSFT]
2005-03-30 11:39:02 UTC
Permalink
Hi Chuck,
If you are trying to refresh the treeview of your NSE, then there is no way
to do this. This is a known issue which has been discussed in following KB:
PRB: Namespace Extension Folder Does Not Update Correctly in Windows
Explorer Tree View (315977)
http://support.microsoft.com/?id=315977

Thanks and regards,
Rhett Gong [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
Chuck Chopp
2005-03-30 12:23:57 UTC
Permalink
Post by Rhett Gong [MSFT]
Hi Chuck,
If you are trying to refresh the treeview of your NSE, then there is no way
PRB: Namespace Extension Folder Does Not Update Correctly in Windows
Explorer Tree View (315977)
http://support.microsoft.com/?id=315977
Thanks for the link to that KB article. I'll review my code and see if my
CShellFolder::GetAttributesOf() method implementation is properly returning
an error code under the correct circumstances.
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Chuck Chopp
2005-03-30 15:03:08 UTC
Permalink
Post by Rhett Gong [MSFT]
Hi Chuck,
If you are trying to refresh the treeview of your NSE, then there is no way
PRB: Namespace Extension Folder Does Not Update Correctly in Windows
Explorer Tree View (315977)
http://support.microsoft.com/?id=315977
OK, beyond my reviewing of my CShellFolder::GetAttributesOf() method
implementation, this still doesn't address the issue of how do I
programmatically initiate a refresh in the shell.

In a nutshell:

Hitting the F5 key while the Windows Explorer has focus causes a refresh to
occur. How do I trigger this to happen programmatically from within a
background worker thread that my NSE creates for the purpose of monitoring
changes to data that affects what my NSE should be displaying?
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Jim Barry
2005-03-30 16:01:23 UTC
Permalink
Post by Chuck Chopp
Hitting the F5 key while the Windows Explorer has focus causes a
refresh to occur. How do I trigger this to happen programmatically
from within a background worker thread that my NSE creates for the
purpose of monitoring changes to data that affects what my NSE should
be displaying?
There is no documented way of triggering an F5 refresh, nor should you need to do that. SHChangeNotify(SHCNE_UPDATEDIR) is the correct way to refresh your namespace.
--
Jim Barry, MVP for Windows SDK
Chuck Chopp
2005-03-30 16:53:39 UTC
Permalink
Post by Jim Barry
There is no documented way of triggering an F5 refresh, nor should you need to do that. SHChangeNotify(SHCNE_UPDATEDIR) is the correct way to refresh your namespace.
What about the shell folder view on the right hand side? Should it also be
refreshed by sending a SHCNE_UPDATEDIR notification?

If so, how do I properly target the "active" folder for which content is
being displayed? Do I need to know the full PIDL chain leading to the
specified folder to specify in the call to SHChangeNotify()?
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
David Candy
2005-03-31 00:34:40 UTC
Permalink
For Each window in AllWindows
If window.locationname="My Computer" then
window.refresh
End If
Next

Refresh is a IE function.
--
----------------------------------------------------------
Post by Chuck Chopp
Post by Jim Barry
There is no documented way of triggering an F5 refresh, nor should you need to do that. SHChangeNotify(SHCNE_UPDATEDIR) is the correct way to refresh your namespace.
What about the shell folder view on the right hand side? Should it also be
refreshed by sending a SHCNE_UPDATEDIR notification?
If so, how do I properly target the "active" folder for which content is
being displayed? Do I need to know the full PIDL chain leading to the
specified folder to specify in the call to SHChangeNotify()?
--
Chuck Chopp
ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com
RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651
Do not send me unsolicited commercial email.
Chuck Chopp
2005-03-31 01:11:56 UTC
Permalink
Post by David Candy
For Each window in AllWindows
If window.locationname="My Computer" then
window.refresh
End If
Next
Refresh is a IE function.
For development of my NSE, I'm working in Visual C/C++ v7 [Visual Studio
2003 .NET], and I'm not using managed code. I don't see where this IE
"Refresh" function is declared, ditto for the "AllWindows" and "Window"
objects. Do you have any pointers to the location in the Platform SDK where
the proper docs can be found?
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
David Candy
2005-03-31 01:48:17 UTC
Permalink
That's in script. AllWindows (how I've named it) is part of IShellDispatch (in C) I think. In the PSDK it's under Shell Objects for Scripting (in the Shell Reference) and is a method under the Shell object.

It returns a collection of shellwindows, each shell window is a IE reference. IE has a method of refresh. I think in C it is IWebBrowser2::Refresh Method. In basic I have two objects (Web Browser and IE) but C only appears to have 1.

Set objShell = CreateObject("Shell.Application")
Set AllWindows=objShell.Windows

Also while looking for IE's refresh in script (which I couldn't find) I came across this, which I think is what I'm doing in script.
IShellView::Refresh
Refreshes the view's contents in response to user input.

HRESULT Refresh(void)Return Values
Returns NOERROR if successful, or an OLE-defined error value otherwise.

Remarks
Tells the view to refresh its contents, revalidating any view information it has.

Notes to Callers
Windows Explorer calls this method when the F5 key is pressed on an already open view.

Notes to Implementers
Refill the view by going to any underlying storage for the contents.


I can only read 20 year old plain C. But this should give you hints on converting to C.
--
----------------------------------------------------------
Post by Chuck Chopp
Post by David Candy
For Each window in AllWindows
If window.locationname="My Computer" then
window.refresh
End If
Next
Refresh is a IE function.
For development of my NSE, I'm working in Visual C/C++ v7 [Visual Studio
2003 .NET], and I'm not using managed code. I don't see where this IE
"Refresh" function is declared, ditto for the "AllWindows" and "Window"
objects. Do you have any pointers to the location in the Platform SDK where
the proper docs can be found?
--
Chuck Chopp
ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com
RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651
Do not send me unsolicited commercial email.
Chuck Chopp
2005-03-31 03:16:32 UTC
Permalink
Close... but not quite, I think.

IShellView::Refresh() is the method in my NSE's CShellView implementation
that gets called in response to a refresh [F5] being initiated by the user.
If my refresh method does get called, then my shell folder view does
refresh itself. However, triggering that refresh from the "outside",
meaning that the code initiating the refresh knows *nothing* about what
particular shell folder is being displayed in any given instance of the
explorer is what's causing me grief.
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Chuck Chopp
2005-04-01 01:03:38 UTC
Permalink
Post by Jim Barry
There is no documented way of triggering an F5 refresh, nor should you need to do that. SHChangeNotify(SHCNE_UPDATEDIR) is the correct way to refresh your namespace.
Interestingly enough, the instances of my CShellFolder class that the shell
uses to display the shell folder tree are *NOT* the same instances that own
the corresponding CShellView instance that is used to display the shell
folder view. I've monitored class constructor calls in the debugger, and I
have observed that there's a certain # of CShellFolder instances created for
use exclusively by the shell folder tree, and then there's one other
instance created for use with a child instance of CShellView.

Even more interesting is the fact that SHChangeNotify(SHCNE_UPDATEDIR) only
refreshes the shell folder tree, while the shell folder view remains
unrefreshed. However, hitting F5 in the shell does force both the shell
folder tree and the shell folder view to refresh themselves.

Now I need to figure out how to trigger the refresh of the shell folder view
and things will be working the way I need them to work.
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Jim Barry
2005-04-01 01:41:41 UTC
Permalink
Post by Chuck Chopp
Even more interesting is the fact that
SHChangeNotify(SHCNE_UPDATEDIR) only refreshes the shell folder tree,
while the shell folder view remains unrefreshed.
Yes. I believe that you need to have your views register themselves with SHChangeNotifyRegister so that they can update themselves when a relevant change event occurs. This is the hole that the CShellFolder::NotifyViews function in the sample code is attempting to plug. The reason that the sample doesn't handle this properly is that SHChangeNotifyRegister was undocumented when the sample was written. If it wasn't for the DOJ antitrust settlement, it would probably still be undocumented today.
--
Jim Barry, MVP for Windows SDK
Chuck Chopp
2005-04-01 02:27:43 UTC
Permalink
Post by Jim Barry
Yes. I believe that you need to have your views register themselves with SHChangeNotifyRegister so that they can update themselves when a relevant change event occurs. This is the hole that the CShellFolder::NotifyViews function in the sample code is attempting to plug. The reason that the sample doesn't handle this properly is that SHChangeNotifyRegister was undocumented when the sample was written. If it wasn't for the DOJ antitrust settlement, it would probably still be undocumented today.
LOL... OK, now we're opening up a much larger can of worms, I think. I
can't say the the "documentation" for SHChangeNotifyRegister() really
qualifies as documentation. Or, perhaps the lack of meaningful examples for
this function in the Platform SDK docs shows a compliances with the letter
of the law but not with the spirit of the law.

My understanding of SHChangeNotifyRegister() is that it allows an arbitary
window to be created and registered to receive shell-related change
notification messages.

If that's a correct understanding, then I take it that my CShellView
implementation would need to register it's shell folder window, or perhaps
the ListView control's window, to receive shell notifications. This would
allow the shell folder view to receive a message that could be interpreted
as meaning that a refresh operation should be performed.

What isn't clear, though, is how to make the call to
SHChangeNotifyRegister() such that only changes to the root of my NSE should
result in a shell change notification message being sent to a window of my
choice.

Are there any decent "concrete" examples of how to use SHChangeNotifyRegister()?
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Chuck Chopp
2005-04-01 03:11:04 UTC
Permalink
Post by Chuck Chopp
Are there any decent "concrete" examples of how to use
SHChangeNotifyRegister()?
I should qualify that request just a bit.... I've done a # of Google
searches, and I've found the one article on GeoCities that discusses
SHChangeNotifyRegister() in a little more detail, including the
dcoumentation of a data structure that contains a PIDL. So, that seems to
help in determining how a notification request can be tied to a specific
portion of the shell's namespace. I'm thinking that what I'd need to do is
to obtain a PIDL for the root folder of my NSE and use it in the call to
SHChangeNotifyRegister().

Whatn I'm not finding is a good clean example of the use of this function in
C/C++. The closest I've gotten is some VB code, so perhaps I'll have to
digest that and see if I can convert it into something workable in C.
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Jim
2005-04-01 03:41:24 UTC
Permalink
Hi,
Post by Chuck Chopp
I should qualify that request just a bit.... I've done a # of Google
searches, and I've found the one article on GeoCities that discusses
SHChangeNotifyRegister() in a little more detail, including the
dcoumentation of a data structure that contains a PIDL. So, that
Caution, this system works different on different OS's. Test it on
all target versions of Windows. Also these are "funny" half baked
PIDL's. Don't use them for anything but identifiying the object. Very
little of the Details (report mode) are stored in them and if you want
to use them to display details it will fail. The PIDLs also don't
belong to you, make copies with IMalloc and let them pass on.
Post by Chuck Chopp
Whatn I'm not finding is a good clean example of the use of this
function in C/C++. The closest I've gotten is some VB code, so
perhaps I'll have to digest that and see if I can convert it into
Can you read Delphi? This may or not be helpful to you.


const
{$EXTERNALSYM SHCNF_ACCEPT_INTERRUPTS}
SHCNF_ACCEPT_INTERRUPTS = $0001;
{$EXTERNALSYM SHCNF_ACCEPT_NON_INTERRUPTS}
SHCNF_ACCEPT_NON_INTERRUPTS = $0002;
{$EXTERNALSYM SHCNF_NO_PROXY}
SHCNF_NO_PROXY = $8000;

type
// Structures for the undocumented ChangeNotify handler
TNotifyRegister = packed record
ItemIDList: PItemIDList;
bWatchSubTree: Bool;
end;

PDWordItemID = ^TDWordItemID;
TDWordItemID = packed record
cb: Word; { Size of Structure }
dwItem1: DWORD;
dwItem2: DWORD;
end;

PShellNotifyRec = ^TShellNotifyRec;
TShellNotifyRec = packed record
PIDL1, // Most ne_xxxx Notifications
PIDL2: PItemIDList;
end;

procedure TVirtualShellChangeThread.RegisterChangeNotify;
var
NR: TNotifyRegister;
Flags, Msg: LongWord;
begin
if (ChangeNotifyHandle = 0) and (NotifyWindowHandle > 0) then
begin
{ Watch everything }
NR.ItemIDList := nil;
NR.bWatchSubTree := True;
Flags := SHCNF_ACCEPT_INTERRUPTS or SHCNF_ACCEPT_NON_INTERRUPTS;
Msg := WM_CHANGENOTIFY;
if (Win32Platform = VER_PLATFORM_WIN32_NT) and
Assigned(SHChangeNotificationLock) and
Assigned(SHChangeNotificationUnlock)
then begin
Flags := Flags or SHCNF_NO_PROXY;
Msg := WM_CHANGENOTIFY_NT
end;
ChangeNotifyHandle := SHChangeNotifyRegister(NotifyWindowHandle,
Flags, SHCNE_ALLEVENTS, Msg, 1, NR);
end;
end;

procedure TVirtualShellChangeThread.UnRegisterChangeNotify;
begin
// Unregister the SHChangeNotify
if ChangeNotifyHandle <> 0 then
SHChangeNotifyDeRegister(ChangeNotifyHandle);
ChangeNotifyHandle := 0
end;

// Window Procedure

function TVirtualShellChangeThread.NotifyWndProc(Wnd: HWND; Msg: UINT;
wParam, lParam: LPARAM): LRESULT;

// Takes the information from the ShellEvent and packs it into a
thread which collects them
// then packs them by combining duplicates.
procedure AddEventToList(Event: LongWord; SNR: PShellNotifyRec;
W1, W2: DWORD);
begin
case Event of
SHCNE_ASSOCCHANGED:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneAssoccChanged, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_ATTRIBUTES:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneAttributes, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_CREATE:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneCreate, SNR.PIDL1, SNR.PIDL2, W1, W2, ThreadPIDLMgr);
SHCNE_DELETE:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneDelete, SNR.PIDL1, SNR.PIDL2, W1, W2, ThreadPIDLMgr);
SHCNE_DRIVEADD:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneDriveAdd, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_DRIVEADDGUI:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneDriveAddGUI, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_DRIVEREMOVED:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneDriveRemoved, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_FREESPACE:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneFreeSpace, nil, nil, PDWordItemID(SNR.PIDL1).dwItem1,
PDWordItemID(SNR.PIDL1).dwItem2, ThreadPIDLMgr);
SHCNE_MEDIAINSERTED:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneMediaInserted, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_MEDIAREMOVED:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneMediaRemoved, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_MKDIR:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneMkDir, SNR.PIDL1, SNR.PIDL2, W1, W2, ThreadPIDLMgr);
SHCNE_NETSHARE:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneNetShare, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_NETUNSHARE:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneNetUnShare, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_RENAMEFOLDER:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneRenameFolder, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_RENAMEITEM:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneRenameItem, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_RMDIR:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneRmDir, SNR.PIDL1, SNR.PIDL2, W1, W2, ThreadPIDLMgr);
SHCNE_SERVERDISCONNECT:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneServerDisconnect, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_UPDATEDIR:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneUpdateDir, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
SHCNE_UPDATEIMAGE:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneUpdateImage, nil, nil,
PDWordItemID(SNR.PIDL1).dwItem1,
PDWordItemID(SNR.PIDL1).dwItem2, ThreadPIDLMgr);
SHCNE_UPDATEITEM:
ChangeNotifier.ChangeDispatchThread.AddEvent(
vsneUpdateItem, SNR.PIDL1, SNR.PIDL2, W1, W2,
ThreadPIDLMgr);
end;
end;


var
Message: TMessage;
Event: DWORD;
Handle: THandle;
SNR: PShellNotifyRec;
Rec: TShellNotifyRec;
i, j: integer;
PIDL: PItemIDList;
OwnP1, OwnP2: Boolean;
begin
Message.Msg := Msg;
Message.lParam := lParam;
Message.wParam := wParam;
Message.Result := 0;
case Msg of
WM_NCCREATE: Message.Result := 1;
{ Message sent by shell }
WM_CHANGENOTIFY_NT:
begin
Handle := SHChangeNotificationLock(WParam, LParam, SNR, Event);
if Handle <> 0 then
try
AddEventToList(Event, SNR, 0, 0);
finally
SHChangeNotificationUnLock(Handle);
end
end;
WM_CHANGENOTIFY:
begin
AddEventToList(lParam, PShellNotifyRec(wParam), 0, 0);

if MapVirtualFolders then
begin
// Due to bug? in 9x we need to generate PIDLs for the My
Documents under
// the desktop if we get one for the physical folder
if Assigned(MyDocsPIDL) then
begin
OwnP1 := False;
OwnP2 := False;
i := ThreadPIDLMgr.IDCount(MyDocsPIDL);
Rec := PShellNotifyRec(wParam)^;
if ILIsParent(MyDocsPIDL, PShellNotifyRec(wParam).PIDL1,
False) then
begin
PIDL := PShellNotifyRec(wParam).PIDL1;
for j := 0 to i - 1 do
PIDL := ThreadPIDLMgr.NextID(PIDL);
Rec.PIDL1 := ThreadPIDLMgr.AppendPIDL(MyDocsDeskPIDL,
PIDL);
OwnP1 := True;
end;
if ILIsParent(MyDocsPIDL, PShellNotifyRec(wParam).PIDL2,
False) then
begin
PIDL := PShellNotifyRec(wParam).PIDL2;
for j := 0 to i - 1 do
PIDL := ThreadPIDLMgr.NextID(PIDL);
Rec.PIDL2 := ThreadPIDLMgr.AppendPIDL(MyDocsDeskPIDL,
PIDL);
OwnP2 := True;
end;
if OwnP1 or OwnP2 then
begin
AddEventToList(lParam, @Rec, 0, 0);
if OwnP1 then
ThreadPIDLMgr.FreePIDL(Rec.PIDL1);
if OwnP2 then
ThreadPIDLMgr.FreePIDL(Rec.PIDL2);
end
end
end;
end;
else
Message.Result := DefWindowProc(NotifyWindowHandle, Msg, wParam,
lParam);
end;
Result := Message.Result;
end;


Jim
--
www.mustangpeak.net
Chuck Chopp
2005-04-01 04:19:44 UTC
Permalink
Post by Jim
Hi,
Post by Chuck Chopp
I should qualify that request just a bit.... I've done a # of Google
searches, and I've found the one article on GeoCities that discusses
SHChangeNotifyRegister() in a little more detail, including the
dcoumentation of a data structure that contains a PIDL. So, that
Caution, this system works different on different OS's. Test it on
all target versions of Windows. Also these are "funny" half baked
PIDL's. Don't use them for anything but identifiying the object. Very
little of the Details (report mode) are stored in them and if you want
to use them to display details it will fail. The PIDLs also don't
belong to you, make copies with IMalloc and let them pass on.
I'll be working with Win2K & newer; there won't be any Win9x/Me running this
code, nor any WinNT v4.0 & older.

As for the PIDLs being "funny", who's generating the PIDLs and is there
anything special to be done w/respect to "decoding" them?

Here's the usage scenario I'm envisioning:

My NSE has a root folder, and I can trigger a refresh of the shell folder
tree under this root folder by calling SHChangeNotify(), specifying
SHCNE_UPDATEDIR, and passing in the path [not PIDL] of "::{my-nse's-guid}".
This works OK now. What I'm expecting to happen, then, is that the call
to SHChangeNotify() will then result in a notification message being sent to
the window who's window handle value was specified in the call to
SHChangeNotifyRegister(). In some way, I need to be able make that call to
SHChangeNotifyRegister() from within an instance of my CShellView class such
that it registers the ListView control's window handle, and the PIDL that's
associated with it is the PIDL for the root folder of my NSE.

Now, assuming that all of that represents a workable means of accomplishing
a CShellView refresh when the root of my NSE handles an updatedir event, I
need to find a way to convert the root folder of my NSE into a PIDL that
will have some meaning to the shell for purposes of delivering a
notification to my shell folder view's ListView control window. It would
appear that calling SHParseDisplayName() and passing it the "::{guid}" form
of my NSE's root folder would do the trick.

I'll catch 40 winks and give it a try in the morning and see if it gets me
the results I'm looking for.
Post by Jim
Can you read Delphi? This may or not be helpful to you.
You mean there's a Delphi developer out there besides me? I still use
Delphi for some projects, albeit it's really some xplatform stuff using
Kylix and the CLX libs, but, hey, at least it's something I'm significantly
more familiar with than VB and is a huge step closer to C/C++ than VB is.
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Jim
2005-04-01 14:48:22 UTC
Permalink
Hi,
Post by Chuck Chopp
I'll be working with Win2K & newer; there won't be any Win9x/Me
running this code, nor any WinNT v4.0 & older.
Win2k will send EVERY notification for EVERY file operation, just what
you would want. XP will take a large operation (like deleting a bunch
of files) and send just an UpdateDir notification (that is what 9x
does). NT4 is an animal all itself, the details of which I don't
recall right now.
Post by Chuck Chopp
As for the PIDLs being "funny", who's generating the PIDLs and is
there anything special to be done w/respect to "decoding" them?
The shell. There is nothing to decodeing them as long as you don't
call function to get more information than their DisplayName and
Attributes. I tried to use them to be the "real" PIDL for the object
after a notification. IShellDetails, the SHxxx function that retrieves
information from PIDL (blanking out on its name), and
IShellFolder2.GetDetailsEx or GetDetailsOf will not be able to extract
any of the extra column details for report mode.
The PIDLs will be fine for that.
Post by Chuck Chopp
Post by Jim
Can you read Delphi? This may or not be helpful to you.
You mean there's a Delphi developer out there besides me? I still
use Delphi for some projects, albeit it's really some xplatform stuff
There are a lot of us <G>. If you have D5 and up download VSTools from
my website and look at the VirtualShellNotifier.pas file. It is way
more complicated than you need as it also wraps the
FindFirstNotification way of finding changes into a Notifier Class then
does all the processing in separate threads, one for the shell
notifications, one for the FindFirst type notification then send them
to a third thread that figures out which ones are duplicates and waits
a few milliseconds to keep "packing" the notifications so my controls
are not refreshing 1000 times for a 1000 files being deleting in Win2k
<G>.

I am also working on the NSE part of my EasyNSE package. Right now it
will do Shell Extensions but I want to extend into NSE's. I think you
don't see many Delphi people here is because the Delphi RTL has a nasty
hard to find bug in DLL's that are heavily loaded with threads making
shell extensions and NSE unstable. It has been there since the first
Win32 compiler and they have finally fixed it in D2005 (but apparently
broke something else) after Mathis and I put in a QC and put the fix on
my web page.

Jim
--
www.mustangpeak.net
Rhett Gong [MSFT]
2005-04-04 10:15:45 UTC
Permalink
Post by Chuck Chopp
Now I need to figure out how to trigger the refresh of the shell folder view
and things will be working the way I need them to work.
I think we discussed this problem before. What about calling refresh on the
IShellView's pointer when you are trying to refresh the view window?


Thanks,
Rhett Gong [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
Chuck Chopp
2005-04-04 13:19:21 UTC
Permalink
Post by Rhett Gong [MSFT]
Post by Chuck Chopp
Now I need to figure out how to trigger the refresh of the shell folder
view
Post by Chuck Chopp
and things will be working the way I need them to work.
I think we discussed this problem before. What about calling refresh on the
IShellView's pointer when you are trying to refresh the view window?
It took making use of SHChangeNotifyRegister() to solve the problem. I had
to have my shell folder view window register for notification of changes
related to the PIDL of the shell folder with which it was associated. When
notification of the change was received, the shell folder view initiated a
refresh of itself.
--
Chuck Chopp

ChuckChopp (at) rtfmcsi (dot) com http://www.rtfmcsi.com

RTFM Consulting Services Inc. 864 801 2795 voice & voicemail
103 Autumn Hill Road 864 801 2774 fax
Greer, SC 29651

Do not send me unsolicited commercial email.
Rhett Gong [MSFT]
2005-04-05 09:56:34 UTC
Permalink
Thanks for your post.
From your previous reply, it seems you are using SHChangeNotifyRegister
with SHCNE_UPDATEDIR which I think it is the way to handle the changes of
an existing folder. How is that going? Please let me know if you need
further assist.

Best regards,
Rhett Gong [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
Loading...