🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
15 messages
15 total messages Started by Matthew Fri, 08 Jun 2007 04:20
EnumWindows etc.
#1930
Author: Matthew
Date: Fri, 08 Jun 2007 04:20
31 lines
1636 bytes
Hi all:

I suck at the API calls... and I need a little help here. I 
have used Enum to get a list of available windows (and procs).
I just want the apps running in the list, but I don't know how 
to differentiate.

The example that came with BCB6:
if(hWnd==NULL)
      return false;

   hg = GlobalAlloc(GMEM_SHARE,sizeof(unsigned long));
   pPid = (unsigned long *)GlobalLock(hg);

   result = GetWindowThreadProcessId(hWnd,pPid);

   if(result){
...etc

Once I have the list, I need to be able to select an app, and
bring it to focus... so if it is minimized to the task bar, how
do I select (code) within my program to maximize it?

Thanks for any help. And if you can tell me how to weed out the
processes and just display the programs on the task bar, that
would also be a great help.

Appreciates all around.

M.
Re: EnumWindows etc.
#1934
Author: Bob Gonder
Date: Fri, 08 Jun 2007 15:10
47 lines
2334 bytes
Matthew wrote:

>have used Enum to get a list of available windows (and procs).
>I just want the apps running in the list, but I don't know how 
>to differentiate.

How to differentiate what?
You will  only get windows.
Are you asking how to know the name of the app that the windows
belongs to?

>The example that came with BCB6:
>if(hWnd==NULL)
>      return false;
>
>   hg = GlobalAlloc(GMEM_SHARE,sizeof(unsigned long));
>   pPid = (unsigned long *)GlobalLock(hg);
>
>   result = GetWindowThreadProcessId(hWnd,pPid);

More straight-forward way:
	DWORD	Pid;
	GetWindowThreadProcessId(hWnd, &Pid);

But I don't think I would bother with that, and go for
	char	title[1024];
	GetWindowText( hWnd, title, 1023 );

Add the hWnd and text to a list (pointer to list passed in lparam)
After the Enum, display and select from the list, use the associated
hWnd to SetForegroundWindow( );

>Once I have the list, I need to be able to select an app, and
>bring it to focus... so if it is minimized to the task bar, how
>do I select (code) within my program to maximize it?

	if( IsIconic( hWnd ) )
	{	ShowWindow( hWnd, SW_RESTORE );
	}else{
		SetForegroundWindow( hWnd );
	};

>Thanks for any help. And if you can tell me how to weed out the
>processes and just display the programs on the task bar, that
>would also be a great help.

There should be no naked processes if you are using EnumWindows
Re: EnumWindows etc.
#1942
Author: Matthew
Date: Sat, 09 Jun 2007 01:00
97 lines
3552 bytes
Bob Gonder wrote:

>How to differentiate what?
>You will  only get windows.
>Are you asking how to know the name of the app that the windows
>belongs to?

Well - I'm using example code, and it does call EnumWindows,
But it lists all processes and all apps that are running. I
don't know why it does both. I am far from an API guy... I
usually do straight C++ code for crunching numbers (number
theory).

>More straight-forward way:
>	DWORD	Pid;
>	GetWindowThreadProcessId(hWnd, &Pid);
>
>But I don't think I would bother with that, and go for
>	char	title[1024];
>	GetWindowText( hWnd, title, 1023 );
>

I will look into this - excellent.

>Add the hWnd and text to a list (pointer to list passed in lparam)
>After the Enum, display and select from the list, use the associated
>hWnd to SetForegroundWindow( );

>> how do I select (code) within my program to maximize it?
>
>	if( IsIconic( hWnd ) )
>	{	ShowWindow( hWnd, SW_RESTORE );
>	}else{
>		SetForegroundWindow( hWnd );
>	};

This is excellent!!! Thank you very much.

>There should be no naked processes if you are using EnumWindows

Well there is - so, instead of a nice short list of running
windows (apps) there's about 40+ processes listed as well...

Here is the function that does the work:

bool __stdcall EnumProc(HWND hWnd,/*LPARAM*/long/*lp*/)
{
   unsigned long* pPid;   //LPDWORD
   unsigned long result;      //DWORD
   void *hg;                  //HGLOBAL
   unsigned long id;

   if(hWnd==NULL)
      return false;

   hg = GlobalAlloc(GMEM_SHARE,sizeof(unsigned long));
   pPid = (unsigned long *)GlobalLock(hg);

   result = GetWindowThreadProcessId(hWnd,pPid);

                                     // the pPid is what is
                                     // also acquiring the 
                                     // procs ???

   if(result){
      char title[110];
      char className[95];
      char totalStr[256];
      GetClassName(hWnd,className,95);
      GetWindowText(hWnd,title,110);
      id=*pPid;
      ultoa(id,totalStr,10);
      strcat(totalStr,"\t");
      if(title){
         strcat(totalStr,title);
         strcat(totalStr,"\t");
      }
      strcat(totalStr,className);
      FormMain->ListBox1->Items->Add((AnsiString)totalStr);
   }
   else{
      GlobalUnlock(hg);
      GlobalFree(hg);
      return false;
   }
   GlobalUnlock(hg);
   GlobalFree(hg);
   return true;
}

Please note I working from example code. And I also hope I
haven't broken protocol by attaching that much code.

Bob - thanks for the help. I really appreciate you time.

Matthew.
Re: EnumWindows etc.
#1943
Author: Ed Mulroy
Date: Sat, 09 Jun 2007 13:36
71 lines
3846 bytes
I think that EnumProc code is unnecessarily complex and is
formatted in a manner which does not help one to easily read
and understand it.

The compiler does not care about an extra space following a
comma or a blank line separating elements such as declarations,
code and if-blocks.  However people more easily read code which
has those things.

The code has several return statements.  While legal this additional
complexity is a complication when debugging.  Since several return
statments are not needed, they can be replaced with one return
statement.

The code does an allocation where one is not needed.  It declares
a 4-byte pointer and then allocates a 4-byte block of memory to
store the returned address.  If instead one merely declared the item
itself, only one 4-byte element is needed and there no longer is the
need to call GlobalAlloc, GlobalLock, GlobalUnlock and GlobalFree.

The EnumWindowsProc function is called internally by Windows and
will always receive a valid window handle.  The code does not need
to test hWnd for NULL.

The call to GetWindowThreadProcessIId with a valid window handle
will always return the process ID so need not be tested for NULL.

Because the intention is to assemble an AnsiString to use in a call
to the ListBox, an AnsiString is used.  However the code plays with
strcat to assemble a char* style string when AnsiString already has
functions to do such things.  Just assemble into an AnsiString from
the beginning using only one char* style string as a buffer.

I do not think your intention was to create a text block ending in a tab
for inclusion in the ListBox.  The tab is to separate the elements that
one can see but not to separate the end of the string from the end of
the displayed element.  This implies the tab should be added prior
to all but the first element.

Here is re-written code to illustrate these points.  I think it is a bit
easier to read and understand.  Try it.  See if it is easier for you.

  ------------------------
  bool __stdcall EnumProc(HWND hWnd, long)
  {
      unsigned long process_id;
      char buffer[128];
      const AnsiString tab_str = '\t';
      AnsiString total_str;

      GetClassName(hWnd, buffer, 95);
      total_str = buffer;

      GetWindowThreadProcessId(hWnd, &process_id);
      ultoa(process_id, buffer, 10);
      total_str = total_str + tab_str + buffer;

      if (GetWindowText(hWnd, buffer, 110)) {
          total_str = total_str + tab_str + buffer;
      }

      FormMain->ListBox1->Items->Add(total_str);
      return true;
  }
  ------------------------ 


.  Ed

> Matthew wrote in message
> news:4669fbaf$1@newsgroups.borland.com...
Re: EnumWindows etc.
#1797
Author: Matthew
Date: Sat, 09 Jun 2007 18:22
44 lines
2307 bytes
Ed Wrote:

>The call to GetWindowThreadProcessIId with a valid window handle
>will always return the process ID so need not be tested for NULL.

Ed, if all I wanted were a list of windows (and not procs)
what would I use/do instead?

I know VERY LITTLE about windows API... I am attempting
to a create a list of (only) running apps, and then have
the ability to select any one of those apps, and maximize,
or minimize it. I don't want to see the procs in my list,
but this code is the only (the one you refer to) example
to go on... So should I use something other than enumproc?


>  ------------------------
>  bool __stdcall EnumProc(HWND hWnd, long)
>  {
>      unsigned long process_id;
>      char buffer[128];
>      const AnsiString tab_str = '\t';
>      AnsiString total_str;
>
>      GetClassName(hWnd, buffer, 95);
>      total_str = buffer;
>
>      GetWindowThreadProcessId(hWnd, &process_id);
>      ultoa(process_id, buffer, 10);
>      total_str = total_str + tab_str + buffer;
>
>      if (GetWindowText(hWnd, buffer, 110)) {
>          total_str = total_str + tab_str + buffer;
>      }
>
>      FormMain->ListBox1->Items->Add(total_str);
>      return true;
>  }
>  ------------------------ 

Excellent - I will test this out as soon as I can.

Thank you for the information and point of view.
Re: EnumWindows etc.
#1798
Author: Bob Gonder
Date: Sat, 09 Jun 2007 22:07
10 lines
1364 bytes
Matthew wrote:

> So should I use something other than enumproc?

I don't think so.
How are you calling EnumProc?

> I don't want to see the procs in my list,

Can you show us the results you are getting?
Re: EnumWindows etc.
#1800
Author: Matthew
Date: Sat, 09 Jun 2007 23:26
57 lines
2881 bytes
Bob Gonder wrote:

>I don't think so.
>How are you calling EnumProc?

void __fastcall TFormMain::SpeedButton4Click(TObject* /*Sender*/)
{
   long lp=0;
   ListBox1->Enabled=true;
   ListBox1->Clear();
   EnumWindows((WNDENUMPROC)EnumProc,lp);
}

The EnumWindows function is transferred to EnumProcs (see 
my former posting to Ed where I include that block of code).

First - Bob, Ed - thanks you both for being patient with my
questions and lack of API understanding. I'm sure I keep 
repeating what I need - but one more time. I need a simple
list of running apps, and the ability to automate withing
my code their status = e.g. if they are minimized, maximized
or focused.

So if I had a single instance of notepad, one of mspaint,
and one of calculator, and they were all minimized, I want
my program (upon execution) to search for 'notepad' and
then to maximize that instance.

>> I don't want to see the procs in my list,
>
>Can you show us the results you are getting?

This is a small portion of the output data:


PID              Caption of Window           Window Class Name

3000             CodeGuard Log               TCodeguardLog
3000             Project Manager             TProjectManager..
3000             Align                       TAlignPalette
3000             C++Builder 6                TApplication
1788             ITouchWin                   AfxFramOrView32
3908             NewsgroupArticleBor...      MSInternetExplo..

Note that out of this list I would only want two in my 
final list - those being C++Builder 6 (an application), and
Windows IE (another application that I'm currently using
to write this message to the news group).

The list is quite long - I'm guessing about 150 items... even
though right now I only have four apps on the task bar.

Thanks again for everything. I have you suggestions saved
in my development logs...

Matthew.
Re: EnumWindows etc.
#1801
Author: Ed Mulroy
Date: Sun, 10 Jun 2007 00:22
59 lines
3182 bytes
I do not know why you need the process id or class name for the window.

I think you are on the right track in using EnumWindows to find the windows 
and writing the captions to the listbox for the user to see.  You would then 
also need to keep an internal list of HWND and window caption.  You can save 
those two items into a structure that you define and use one of a vector 
(best) or a TList (not best) for the list.

When the user double clicks on a caption in the list box you can then go 
through your internal list and find the associated window handle, the HWND. 
You can then test its state with IsIconic and IsZoomed and decide what to do 
with it.

.  Ed

> Matthew wrote in message
> news:466aefff$1@newsgroups.borland.com...
>
>>The call to GetWindowThreadProcessIId with a valid window handle
>>will always return the process ID so need not be tested for NULL.
>
> Ed, if all I wanted were a list of windows (and not procs)
> what would I use/do instead?
>
> I know VERY LITTLE about windows API... I am attempting
> to a create a list of (only) running apps, and then have
> the ability to select any one of those apps, and maximize,
> or minimize it. I don't want to see the procs in my list,
> but this code is the only (the one you refer to) example
> to go on... So should I use something other than enumproc?
>
>
>>  ------------------------
>>  bool __stdcall EnumProc(HWND hWnd, long)
>>  {
>>      unsigned long process_id;
>>      char buffer[128];
>>      const AnsiString tab_str = '\t';
>>      AnsiString total_str;
>>
>>      GetClassName(hWnd, buffer, 95);
>>      total_str = buffer;
>>
>>      GetWindowThreadProcessId(hWnd, &process_id);
>>      ultoa(process_id, buffer, 10);
>>      total_str = total_str + tab_str + buffer;
>>
>>      if (GetWindowText(hWnd, buffer, 110)) {
>>          total_str = total_str + tab_str + buffer;
>>      }
>>
>>      FormMain->ListBox1->Items->Add(total_str);
>>      return true;
>>  }
>>  ------------------------ 
>
> Excellent - I will test this out as soon as I can.
>
> Thank you for the information and point of view.
Re: EnumWindows etc.
#1802
Author: Matthew
Date: Sun, 10 Jun 2007 01:32
40 lines
2493 bytes
Ed wrote:

>I do not know why you need the process id or class name for the window.

As far as I know - I don't need the ID or class name. The code
I am using is example code from C++ BCB 6 - and I'm wading
through in an attempt to understand the necessary API calls
to do what I getting at.

>keep an internal list of HWND and window caption.  You can save 
>those two items into a structure that you define and use one 

I would perfer to have a linked list (or the kind) of HWND.
Can you please show me how to declare that struct?

e.g. - does the struct need pointer types? And if so, what
type are they?

>When the user double clicks on a caption in the list box you can then go 
>through your internal list and find the associated window handle, the HWND. 

>You can then test its state with IsIconic and IsZoomed and decide what to do 
>with it.

Yeah - Bob said that IsIconic and IsZoomed are two calls I
have to look at. I have Win32 Programming reference by:
Rector / Newcomer (Addison Wesley publication)... But the
references are cryptic and contain little examples.

I'm assuming that if I have a list of HWND - that one of the
structs components will have a pointer reference to the 
window I wish to affect with IsIconic, and IsZoomed.

Once I have the state of the window, what API call do I use
to maximize or minimize it?

Again - thanks for keeping this thread alive with answers.

Matthew.
Re: EnumWindows etc.
#1803
Author: Ed Mulroy
Date: Sun, 10 Jun 2007 01:51
85 lines
4532 bytes
> I would perfer to have a linked list (or the kind) of HWND.
> Can you please show me how to declare that struct?

Ok, a structure to use in a doubly linked list:

struct WindowData
    {
    HWND hwnd;
    AnsiString caption;
    WindowData *prev_item;
    WindowData *next_item;
    };

However that means you must allocate each node (each instance of the 
structure), keep copies of the addresses of the first and current items and 
adjust the links yourself.  However doing a linked list yourself is a lot of 
coding and I don't see how this task needs an actual linked list rather than 
a simple array.

You might consider using what the language provides.  You could use a vector 
(a standard C++ item) it does the allocation for you and handles things as 
an array.  C++ provides functions that you can use to sort the vector and 
search for an instance containing a matching item.

> ...I have Win32 Programming reference by:
> Rector / Newcomer (Addison Wesley publication)... But the
> references are cryptic and contain little examples...

The compiler came with a Win32 help file that you can use.  Since Windows is 
from Microsoft they provide MSDN, Microsoft Developer Network, and it has 
examples, although some suffer from undue complication such as the obviously 
1991 vintage example for EnumProc that you were using.
  http://msdn2.microsoft.com/en-us/Library

I have some programming pages posted with links to tutorials and other 
information.  Look at them and see if they help:
  http://www.mulroy.org/programg.htm

> Once I have the state of the window, what API call do I use
> to maximize or minimize it?

Look at the function ShowWindow
  http://msdn2.microsoft.com/en-us/library/ms633548.aspx

.  Ed

> Matthew wrote in message
> news:466b54ac$1@newsgroups.borland.com...
>
>>I do not know why you need the process id or class name for the window.
>
> As far as I know - I don't need the ID or class name. The code
> I am using is example code from C++ BCB 6 - and I'm wading
> through in an attempt to understand the necessary API calls
> to do what I getting at.
>
>>keep an internal list of HWND and window caption.  You can save
>>those two items into a structure that you define and use one
>
> I would perfer to have a linked list (or the kind) of HWND.
> Can you please show me how to declare that struct?
>
> e.g. - does the struct need pointer types? And if so, what
> type are they?
>
>>When the user double clicks on a caption in the list box you can
>>then go through your internal list and find the associated window
>>handle, the HWND.
>
>>You can then test its state with IsIconic and IsZoomed and decide
>>what to do with it.
>
> Yeah - Bob said that IsIconic and IsZoomed are two calls I
> have to look at. I have Win32 Programming reference by:
> Rector / Newcomer (Addison Wesley publication)... But the
> references are cryptic and contain little examples.
>
> I'm assuming that if I have a list of HWND - that one of the
> structs components will have a pointer reference to the
> window I wish to affect with IsIconic, and IsZoomed.
>
> Once I have the state of the window, what API call do I use
> to maximize or minimize it?
>
> Again - thanks for keeping this thread alive with answers.
Re: EnumWindows etc.
#1805
Author: Matthew
Date: Sun, 10 Jun 2007 02:53
68 lines
3310 bytes
Ed wrote:

>Ok, a structure to use in a doubly linked list:
>
>struct WindowData
>    {
>    HWND hwnd;
>    AnsiString caption;
>    WindowData *prev_item;
>    WindowData *next_item;
>    };
>

>However that means you must allocate each node (each instance of the structure), keep copies of the addresses of the first and current items and 
>adjust the links yourself.  However doing a linked list yourself is a lot of 
>coding and I don't see how this task needs an actual linked list rather than 
>a simple array.

When it comes to the C code, that's super easy for me. I have
a forest class that I've been using for years to organize
data, and all the handling routines are already in place
including virtual functions that do some simple but cool
tasks. 

And yeah - an array will do the same... I'm just used to 
using the link classes I've used for years. The forest class
I built allows each node to link to infinite nodes. The hard
part in building that was a method to collapse the forest 
without memory loss... :) [e.g. it's not doubly linked, it's
infinitely linked] - and I had to develop it for number theory
and simulated annealing multi-depth related paradigms.

I don't usually mess around with windows functions. I usually
just write code to crunch numbers = primes, pi, etc... in
an attempt to do it as fast as possible.

As for the struct:

>    HWND hwnd;
>    AnsiString caption;

That's what I needed. Thank you very much. I didn't realize
that HWND was available as an actual type. I'm assuming that's
declared in windows.h???

>  http://msdn2.microsoft.com/en-us/Library
>
>I have some programming pages posted with links to tutorials and other 
>information.  Look at them and see if they help:
>  http://www.mulroy.org/programg.htm
>
>> Once I have the state of the window, what API call do I use
>> to maximize or minimize it?
>
>Look at the function ShowWindow
>  http://msdn2.microsoft.com/en-us/library/ms633548.aspx
>
>.  Ed

The ShowWindow is the last key to what I need.

You have been a great help. I will take a look at all the
links. From here, I think I know what I need.

You are much appreciated!

Matthew.
Re: EnumWindows etc.
#1806
Author: Matthew
Date: Sun, 10 Jun 2007 02:55
12 lines
1337 bytes
Ed Wrote:

>I have some programming pages posted with links to tutorials and other 
>information.  Look at them and see if they help:
>  http://www.mulroy.org/programg.htm

Wow - that's an extensive site. Are you responsible for that?
That's remarkable - I will be recommending it to my fellow
programmers.

Matthew.
Re: EnumWindows etc.
#1809
Author: Ed Mulroy
Date: Sun, 10 Jun 2007 14:21
20 lines
2067 bytes
> Wow - that's an extensive site. Are you responsible for that?

Yes, that's my site.  I hope it helps people find information useful to 
them.  The address is a re-director.  Note that if the one ISP is down I can 
reconfigure mulroy.org to point to a mirror site.  If you bookmark where it 
ends up and not mulroy.org you'll only have the address for the one and 
loose the benefit of the redirection.

.  Ed

> Matthew wrote in message
> news:466b681f$1@newsgroups.borland.com...
>
>>I have some programming pages posted with links to tutorials
>>and other information.  Look at them and see if they help:
>>  http://www.mulroy.org/programg.htm
>
> Wow - that's an extensive site. Are you responsible for that?
> That's remarkable - I will be recommending it to my fellow
> programmers.
Re: EnumWindows etc.
#1810
Author: Ed Mulroy
Date: Sun, 10 Jun 2007 14:32
98 lines
4935 bytes
> When it comes to the C code, that's super easy for me...

I misjudged you.  I thought you were new to this and missed that what you 
were new to was the vagarities of Windows and of C++.

> ...I didn't realize that HWND was available as an actual type.
> I'm assuming that's declared in windows.h???...

Yes.  Windows.h actually does a number of includes itself.  By including 
that file you get many typedefs, macros and structure definitions as well as 
the function prototypes for what Windows provides.

Note that if you are writing a VCL based program (most of what I do is not 
VCL), you probably don't need to include windows.h because vcl.h provides 
what you need.

There is one additional thing you need to know.  Long ago Microsoft did not 
support C++ so did Windows headers for old-timey C (K&R 1, pre-ANSI standard 
C).  These days functions prototypes are checked against use of those 
functions for proper argument lists.  If you get an error on the EnumProc 
argument of EnumWindows then either put this as the first line in the file

#define STRICT

or define it under Options|Project defines.  STRICT is Microsoft's 
workaround to alter the expansion of windows.h to support the "new" way 
stuff has been done (since the late 80's! ).

.  Ed

> Matthew wrote in message
> news:466b6796$1@newsgroups.borland.com...
>
>>Ok, a structure to use in a doubly linked list:
>>
>>struct WindowData
>>    {
>>    HWND hwnd;
>>    AnsiString caption;
>>    WindowData *prev_item;
>>    WindowData *next_item;
>>    };
>>
>
>>However that means you must allocate each node (each
>> instance of the structure), keep copies of the addresses of
>> the first and current items and adjust the links yourself.
>> However doing a linked list yourself is a lot of coding and
>> I don't see how this task needs an actual linked list rather
>> than a simple array.
>
> When it comes to the C code, that's super easy for me. I have
> a forest class that I've been using for years to organize
> data, and all the handling routines are already in place
> including virtual functions that do some simple but cool
> tasks.
>
> And yeah - an array will do the same... I'm just used to
> using the link classes I've used for years. The forest class
> I built allows each node to link to infinite nodes. The hard
> part in building that was a method to collapse the forest
> without memory loss... :) [e.g. it's not doubly linked, it's
> infinitely linked] - and I had to develop it for number theory
> and simulated annealing multi-depth related paradigms.
>
> I don't usually mess around with windows functions. I usually
> just write code to crunch numbers = primes, pi, etc... in
> an attempt to do it as fast as possible.
>
> As for the struct:
>
>>    HWND hwnd;
>>    AnsiString caption;
>
> That's what I needed. Thank you very much. I didn't realize
> that HWND was available as an actual type. I'm assuming
> that's declared in windows.h???
>
>>  http://msdn2.microsoft.com/en-us/Library
>>
>>I have some programming pages posted with links to tutorials and other
>>information.  Look at them and see if they help:
>>  http://www.mulroy.org/programg.htm
>>
>>> Once I have the state of the window, what API call do I use
>>> to maximize or minimize it?
>>
>>Look at the function ShowWindow
>>  http://msdn2.microsoft.com/en-us/library/ms633548.aspx
>>
>>.  Ed
>
> The ShowWindow is the last key to what I need.
>
> You have been a great help. I will take a look at all the
> links. From here, I think I know what I need.
>
> You are much appreciated!
Re: EnumWindows etc.
#1814
Author: Matthew
Date: Sun, 10 Jun 2007 23:08
20 lines
1947 bytes
Ed Wrote:

>There is one additional thing you need to know.  Long ago Microsoft did not 
>support C++ so did Windows headers for old-timey C (K&R 1, pre-ANSI standard 
>C).  These days functions prototypes are checked against use of those 
>functions for proper argument lists.  If you get an error on the EnumProc 
>argument of EnumWindows then either put this as the first line in the file
>
>#define STRICT

A toggle for 'super'-strongly typecasting... hahaha... But
I've seen worse. And speaking of K&R, I actually have a copy
of "The C Programming Language" on my shelf for decorations
sake.

Thanks for all the help with the API calls. I have already
shared your website with my other compadre's.

Matthew.
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads