This is a function I grabbed from the blizz chatframes file and tweaked it for my purposes somewhat. You can ignore the infoPanel sections as that is something I use so that my chat frame addons can talk to each other by validating that flag to know whether it can use that chat frame or not for their own uses.
Code:
--[[ Generate a list of active frames for locating an available frame to use ]]--
local function nUI_InfoPanel_Chat_ActiveFrames()
local shownList = {};
local dockedList = {};
local infoPanelList = {};
local count = 0;
local chatFrame;
-- Cycle through ChatFrames 1 to 10 ( the current NUM_CHAT_WINDOWS setting )
for i=1, NUM_CHAT_WINDOWS do
-- Get the chatFrame object for this possible frame
chatFrame = _G["ChatFrame"..i];
-- Is it supposed to be shown ?
local _, _, _, _, _, _, shown = FCF_GetChatWindowInfo(i);
-- ChatFrame should be valid but double check
if ( chatFrame ) then
-- If it is flagged as a shown window then add it to the shown list
if ( shown ) then shownList[chatFrame:GetID()] = true; end
-- If it is flagged as a docked window then add it to the docked list
if ( chatFrame.isDocked ) then dockedList[chatFrame:GetID()] = true; end
-- If an info panel is using it then we don't want to use it
if ( chatFrame.infoPanel ) then infoPanelList[chatFrame:GetID()] = true; end
end
end
-- return the lists for viewing later
return shownList,dockedList,infoPanelList;
end
And this is the section of code I use it in ..
Code:
-- If blizz is updating the chat windows then we want in so we can do our stuff
elseif ( event == "UPDATE_CHAT_WINDOWS" ) then
-- Get the current list of frames
local shownList,dockedList,infoPanelList = nUI_InfoPanel_Chat_ActiveFrames();
-- Use the one stored in the saved variables table
gcframe = _G[ipc_chatFrame];
local inUse = 0;
-- Go through the list of available chat frames
for i = 1, NUM_CHAT_WINDOWS do
-- If we have already stored the frame to use then use it and don't bother looking anymore.
if ( gcframe ) then
gcframe.infoPanel = true;
nUI_InfoPanel_Chat_Restore();
break;
end
-- Generate a chat frame object
local cf = _G["ChatFrame"..i];
-- If it is not in the shown or docked list then it *should* be available for use
if ( not shownList[cf:GetID()] and not dockedList[cf:GetID()] and not infoPanelList[cf:GetID()] ) then
-- Set our special variable with the frame we're gonna use
gcframe = _G["ChatFrame"..i];
-- Tell us that we are using it in an infoPanel as that isn't docked or shown
gcframe.infoPanel = true;
-- Initialise the rest of its settings
nUI_InfoPanel_Chat_Initialise();
-- We made our frame so we can stop looking for a spot
break;
These two are pretty much the meat of my chat frame addons so hopefully they will help give you some ideas alongside those of zorks suggestions.