1. Find.Execute with Find.Format = True keeps looping - Word VBA
2. Find Loop only works on first 3 of find.execute then stops
Can anyone please tell me why this macro works on the first three occurances
of finding strFind (of a total of 43 occurances) and then stops after the
third occurance of finding strFind with a message:
Code Execution has been interrupted.
When I click Debug, this line in the code is highlighted in Yellow:
If Not Selection.Find.Found Then Exit Do
MACRO:
Sub findandType()
Dim strFind As String
Dim strTypeTxt As String
strFind = "Site Address"
strTypeTxt = "Site City:"
Selection.HomeKey Unit:=wdStory ' move to top of document
Do ' STARTS LOOP
With Selection.Find
.Text = strFind
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop 'CRITICAL so not asked to continue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute
If Not Selection.Find.Found Then Exit Do ' STOP IF NOT FOUND ANYMORE
'STUFF TO DO AFTER TEXT IS FOUND
Selection.MoveDown Unit:=wdLine, Count:=1 'move down one line
Selection.HomeKey Unit:=wdLine 'move to the beginning
of the line
Selection.TypeText Text:=strTypeTxt 'type this text
'find the next occurance of strFind
Loop
End Sub
3. Infinite Loop with a find and replace - Word VBA
4. Returning object from AsyncCallback called inside a threaded Infinite loop
Jim:
I'm not entirely sure that I understand the question. Let me throw what I
picked up back at you, and you can maybe correct me if I'm wrong:
I assume that the code that you posted all works, except that you have a
scoping issue where you cannot inform the main form that something has been
acted upon because inside your OnReadComplete method, the main form (or the
form that you want to notify) is not in scope. Is that correct?
Assuming that's right, you could could always make a reference to the main
form (or better yet, some kind of broker object) available to the thread
code, which would, in turn, add the reference to your state object:
(warning, this is off the cuff, might need adjustment to compile)
So, what could happen would be that you have an "observer" class that sits
between the form(s) and the state class. The class with the thread has a
reference to it, so that it (the observer) can be added to the state class:
form(s) ------ Observer ------ State
State notifies the observer, and the observer fires an event that can be
subscribed by multiple forms or other objects.
public delegate void MessageReceivedEventHandler(object sender,
MessageReceivedEventArgs e);
public class MessageReceivedEventArgs
{
public MessageReceivedEventArgs(string message)
{
this.Message = message;
}
public string Message; // probably make this a property, leaving it out
for brevity
}
public class SocketReadObserver
{
public event MessageReceivedEventHandler MessageReceived;
public void ActOn(string message)
{
if(this.MessageReceived != null)
this.MessageReceived(this, new
MessageReceivedEventArgs(message);
}
}
Now, your State class calls the SocketReadObserver's ActOnMethod.
You need to somehow have SocketReadObserver in scope. You could use a
singleton for this, or your main form could instance one and pass to the
class that contains the thread. Or, perhaps the object that owns the thread
also owns the observer.
The benefit of breaking it out into an observer is that any object
(including the main form) that is interested in receive events can subscribe
to the event:
public class TheThreadClass
{
public SocketReadObserver Observer;
public void TheInfiniteLoopMethod
{
//same code as before
// except provide the listener to the state class
handler.Observer = this.Observer;
}
}
// state object calls Observer.ActOn(message) when the message completes
// oh, don't forget the main form code:
// main form:
// here's the code that starts the thread:
// note the observer has to be created somewhere
// in this example, the form will do it, but you might want to originate it
elsewhere
..
SocketReadObserver observer = new SocketReadObserver();
theThreadListenerObject.Observer = observer;
observer.MessageReceived += new
MessageReceivedEventHandler(this.MessageReceived);
// note, you can hook as many interested parties as you have to this
event -- system tray item, toolbar item, whatever:
public void MessageReceived(object sender, MessageReceivedEventArgs e)
{
// important: this event will not be called by the main thread, but if
you want to do _anything_ that changes
// a gui control, you _must_ make it happen on the main thread. Use
Invoke for this:
if(this.InvokeRequired)
this.Invoke(new
MessageReceivedEventHandler(this.MessageReceived), object[] {sender, e});
else
{
// do your form stuff here
}
}
PS depending upon what you were doing, there are probably a number of ways
that you can optimize this, I was just trying to get the idea across.
PSS: If this isn't the problem that you've had, I'm sorry for being a
windbag <g>
"Jim P." < XXXX@XXXXX.COM > wrote in message
news:uqkoNce% XXXX@XXXXX.COM ...
> I'm having trouble returning an object from an AsyncCallback called inside
a
> threaded infinite loop.
>
> I'm working on a Peer2Peer app that uses an AsyncCallback to rerieve the
> data from the remote peer. I have no problem connecting the peers and
> streaming Network Streams. When the incoming data is finished recieving,
I
> act upon it. This works great as long as all of the code is inside my
form.
>
> I want to build the networking code into a seperate assembly (to be used
by
> a server and client apps). It works fine but I can't return the value
back
> to the Main Form. How can I pass back the retrieved data through the
> following steps?? Or, any other strategies on how to tackle this problem?
>
> The Current Process
> I start the listener inside a thread and begin an infinite loop to check
for
> a client connection. When a client connects I call a method that starts
the
> .BeginRead on the Network Stream. The .BeginRead uses an AsyncCallback
> delegate called 'OnReadComplete' and passes a StateObject with the
connected
> socket.. Inside OnReadComplete, I transfer the callback object to a new
> StateObject. I recieve data in 256 byte chunks until the bytes recieved
> equals 0. Then I act on that data.
>
> Some example code:
>
> ** State Object
> ----------------
> public class StateObject
> {
> public System.Net.Sockets.Socket socket;
> public byte[] buffer = new byte[256];
> public NetworkStream networkStream;
>
> public AsyncCallback callbackRead;
> }
>
> ** Infinite loop used after starting listener
> ------------------------------------------
> // keep listening until you recieve a connection
> for (;;)
> {
> // if client connects, accept the connection
> // and return a new socket named socketForClient
> // while tcpListener keeps listening
> Socket socketForClient = tcpListener.AcceptSocket();
> if (socketForClient.Connected)
> {
> StateObject handler = new StateObject();
> handler.socket = socketForClient;
> handler.networkStream = new NetworkStream(socketForClient);
> handler.callbackRead = new AsyncCallback(this.OnReadComplete);
> StartRead(handler);
> }
> }
>
> ** StartRead
> -------------
> public void StartRead(StateObject handler)
> {
> handler.networkStream.BeginRead(
> handler.buffer, 0, handler.buffer.Length, handler.callbackRead,
handler);
> }
>
> ** OnReadComplete
> ----------------------
> private void OnReadComplete( IAsyncResult ar )
> {
> // Get the socket
> StateObject newSocket = (StateObject)ar.AsyncState;
> Socket client = newSocket.socket;
>
> // Get the networkStream
> NetworkStream readStream = new NetworkStream(newSocket.socket);
>
> int bytesRead = readStream.EndRead(ar);
>
> // If there is data left to be retieved
> if( bytesRead > 0 )
> {
> string s = System.Text.Encoding.ASCII.GetString( newSocket.buffer, 0,
> bytesRead );
> readStream.BeginRead( newSocket.buffer, 0, newSocket.buffer.Length,
> newSocket.callbackRead, newSocket);
> // Store message into string.
> message += s;
> }
> // The incoming stream has finished
> else
> {
> // Act on Incoming Message
> actOn(message);
>
> // Close out all objects
> newSocket.networkStream.Close();
> newSocket.socket.Close();
> newSocket.networkStream = null;
> newSocket.socket = null;
> message = null;
> }
> }
>
>
> Thanks,
> Jim
>
>
5. Infinite loop in _AfxRemoveDefaultButton in mfc71ud.dll - help!
6. Need help with TDrawGrid DrawCell stuck in infinite loop
I'm relatively new to Delphi and I'm having a bear of a time trying to
understand what I'm doing wrong with this DrawGrid. I've got the following
code:
TResultsGrid = class(TDrawGrid)
ResultsSet: TResultsSet;
private
fTypeList,
fNameList: TStringList;
fSavedFile: string;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState:
TGridDrawState); override;
procedure AssignColTypes(TypeList: TStringList);
procedure AssignColNames(NameList: TStringList);
procedure Save;
procedure SaveAs;
procedure Print;
end;
procedure TResultsGrid.DrawCell(ACol, ARow: Longint; ARect: TRect; AState:
TGridDrawState);
begin
if ARow = 0 then
self.Canvas.TextOut(ARect.Left, ARect.Top, fNameList.Strings[ACol])
else
self.Canvas.TextOut(ARect.Left, ARect.Top, ResultsSet.GetRow(ARow -
1).Strings[ACol]);
end;
For some reason I'm getting an EStringListError with message 'List index out
of bounds[2]', but when I set a break point within the DrawCell procedure
the value of ARow and ACol are always zero. I'm dynamically creating the
drawgrid with the code below:
fResultsSet[fGrids - 1] := TResultsGrid.Create (ResultsScrollBox);
fResultsSet[fGrids - 1].Parent := ResultsScrollBox;
fResultsSet[fGrids - 1].Options :=
[goFixedVertLine,goFixedHorzLine,goVertLine,goHorzLine,goRangeSelect,goColSi
zing];
fResultsSet[fGrids - 1].Height := ResultsTab.Height;
fResultsSet[fGrids - 1].Align := alClient;
ColTypes.Insert(0, 'integer');
fResultsSet[fGrids - 1].AssignColTypes (ColTypes);
ColNames.Insert(0, '');
fResultsSet[fGrids - 1].AssignColNames (ColNames);
fResultsSet[fGrids - 1].ResultsSet := ResultsSet;
fResultsSet[fGrids - 1].ColCount := Columns + 1;
fResultsSet[fGrids - 1].RowCount := ResultsSet.Count + 1;
if fResultsSet[fGrids - 1].RowCount < 2 then
fResultsSet[fGrids - 1].RowCount := 2;
fResultsSet[fGrids - 1].FixedRows := 1;
Any ideas will be helpfull...
Thanks,
-Charles