📄 rtbutton.cpp
字号:
//===========================================================================
//
// Module: RTBUTTON.CPP
//
// Syntax: RTBUTTON [<button title> [<database> [<Server>]]]
// Note: All the arguments are optional, but must be in the
// order specified.
//
// Description:
// Sample C++ API program that creates, edits and deletes rich
// text buttons using the LNButton and LNCompositeData classes.
//
//
//
//===========================================================================
#include "rtbutton.hpp"
// Input parameter strings.
IOParameter CommandBuf;
IOParameter PromptString1;
IOParameter ParamString1;
IOParameter PromptString2;
IOParameter ParamString2;
IOParameter PromptString3;
IOParameter ParamString3;
//---------------------------------------------------------------------------
//
// MAIN
//
//---------------------------------------------------------------------------
int main(int argc, char *argv[])
{
int ProgramStatus = 0;
LNNotesSession Session;
// Begin TRY block.
// Throw all errors encountered during command execution.
LNSetThrowAllErrors (TRUE);
try
{
LNDatabase DocDB;
LNString DatabasePath;
LNString ServerPath;
LNString ButtonTitle;
LNDocumentArray DocArray;
LNString SearchFormula;
// Initialize the API.
Session.Init (argc, argv);
// Parse the argument list.
ProcessArguments (argc, argv, &DatabasePath, &ServerPath, &ButtonTitle);
// Get the specified Notes database.
Session.GetDatabase(DatabasePath, &DocDB, ServerPath);
// Open the database.
DocDB.Open();
// Get an array of all the docs in the database.
DocDB.GetDocuments( &DocArray );
LNINT Index;
LNBOOL IsDocFound1 = FALSE;
LNBOOL IsDocFound2 = FALSE;
LNINT Count = DocArray.GetCount();
LNString FormulaString("@Prompt([Ok];\"Greeting\";\"Hi, how are you?!\")");
LNDocument CurDoc;
LNText Subject;
LNString SubjectString;
LNButton Button1, Button2, Button3;
LNRichText RT1, RT2, RT3;
LNString NewLabel("New Label");
// Loop through the documents until we find the two documents
// that this sample is supposed to use
for (Index=0; Index<Count; Index++)
{
// Get the next document in the array.
CurDoc = DocArray[Index];
// Open it.
CurDoc.Open( LNNOTEOPENFLAGS_DEFAULT );
// Check the subject of each document to find the two documents that we need
if ( CurDoc.HasItem("Subject"))
{
CurDoc.GetItem("Subject", &Subject);
Subject.GetText(&SubjectString);
if (LNStringCompare(SubjectString, "Rtbutton using LNButton class") == 0)
{
// Let's create 3 buttons using LNButton class
AppendButton(ButtonTitle, FormulaString, &CurDoc, &Button1);
AppendButton(ButtonTitle, FormulaString, &CurDoc, &Button2);
AppendButton(ButtonTitle, FormulaString, &CurDoc, &Button3);
// Save the note to disk, otherwise all the work is wasted.
CurDoc.Save();
// You can now check the document and make sure that it contains 3 buttons.
// Now let's edit the second button that we just created.
// We'll change its label to the NewLabel string, defined above.
Button2.SetLabel(NewLabel);
// And again, save the document.
CurDoc.Save();
cout << "Buttons created with LNButton class added and saved" << endl;
cout << "Hit Return to continue: ";
cin >> CommandBuf;
// Now let's delete Button3 that we created earlier.
DeleteButton(&CurDoc, &Button3);
// Save the document.
CurDoc.Save();
cout << "Button3 created with LNButton class deleted" << endl;
IsDocFound1 = TRUE;
if (IsDocFound2) // found both documents, don't need to iterate any more.
break;
}
else if (LNStringCompare(SubjectString, "Rtbutton using CD Records") == 0)
{
// Here we'll create 3 buttons using CD records and append them
// to the document.
AppendCDButton(ButtonTitle, FormulaString, &CurDoc, &RT1);
AppendCDButton(ButtonTitle, FormulaString, &CurDoc, &RT2);
AppendCDButton(ButtonTitle, FormulaString, &CurDoc, &RT3);
// Save the note to disk, otherwise all the work is wasted.
CurDoc.Save();
// You can now check the document and make sure that
// it contains 3 buttons created with CD Records.
// Now we'll show how to modify the button (change its label)
// using CD records.
EditCDButtonLabel(NewLabel, &RT2);
CurDoc.Save();
cout << "Buttons created with CD records added and saved" << endl;
cout << "Hit Return to continue: ";
cin >> CommandBuf;
// You can now check the document and make sure that the second
// button has a different label
// Now we'll delete the third button we created using CD records
DeleteCDButton(&RT3);
CurDoc.Save();
cout << "Button3 created with CD records deleted" << endl;
IsDocFound2 = TRUE;
if (IsDocFound1) // found both documents, don't need to iterate any more
break;
}
}
CurDoc.Save();
// Always close it, too! Conserve memory!
CurDoc.Close();
}
if (!IsDocFound1)
{
cout << "This database contains no documents with \"Rtbutton using LNButton class\" subject." << endl;
cout << "Unable to create buttons using LNButton class." << endl;
}
if (!IsDocFound2)
{
cout << "This database contains no documents with \"Rtbutton using CD records\" subject." << endl;
cout << "Unable to create buttons using CD records." << endl;
}
// Close the database.
DocDB.Close();
ProgramStatus = 0;
} // END try
catch (LNSTATUS Lnerror)
{
char ErrorBuf[LNERROR_MESSAGE_LENGTH];
LNGetErrorMessage(Lnerror, ErrorBuf);
cout << "\nError: " << ErrorBuf << endl;
ProgramStatus = 2;
}
catch (const char *ErrorMessage)
{
cout << "\nError: " << ErrorMessage << endl << endl;
ProgramStatus = 1;
}
cout << endl;
cout << "Hit Return To Exit: ";
cin >> CommandBuf;
// Terminate the API.
Session.Term();
return (ProgramStatus);
} // END MAIN
//---------------------------------------------------------------------------
// Name:
// AppendButton
//
// Description:
// Creates a button using LNButton class, and appends it to the
// body of the document that is passed in.
//
//
//---------------------------------------------------------------------------
void AppendButton (const LNString &ButtonTitle, const LNString &FormulaString,
LNDocument *CurDoc, LNButton* Button)
{
LNRichText RT;
LNRTCursor Cursor;
LNSetThrowAllErrors (TRUE);
//Create a button in a document using LNButton class.
CurDoc->GetItem("Body",&RT);
RT.GetEndCursor(&Cursor);
// Create a formula
LNFormula Formula(FormulaString);
// Construct a button that contains the above formula. Then
// insert the button into the rich text item.
RT.Insert("\n\nThis button was made using LNButton class: ", &Cursor);
RT.CreateButton(ButtonTitle, Formula, &Cursor, Button);
RT.Insert("\n\n", &Cursor);
} // END AppendButton()
//---------------------------------------------------------------------------
//
// Name:
// AppendCDButton
//
// Description:
// Creates a button hotspot and appends this to the body field of the
// LNDocument passed in.
//
//---------------------------------------------------------------------------
void AppendCDButton(const LNString &ButtonTitle, const LNString &FormulaString,
LNDocument *CurDoc, LNRichText *RT)
{
LNSTATUS Error;
CDHOTSPOTBEGIN Hotspotbegin;
CDBUTTON Button;
CDHOTSPOTEND Hotspotend;
HANDLE FormulaHandle;
void* FormulaBuf;
WORD Wnop;
STATUS Werr;
LNString Formula;
LNCompositeData CD;
WORD Length;
// Get the rich text "Body" field from the document. We will append the button to it.
CurDoc->GetItem("Body", RT);
// Append a string to the end of the field where the button will follow.
RT->Append( "\nThis button was made using CD records: ");
// Specify a formula (in text format) for the button.
Formula = FormulaString;
//Formula = "@Prompt([OKCANCELEDIT];\"Search Criteria\";\"Please enter your name:\";\"\" )";
// Assume no search formula.
FormulaHandle = NULLHANDLE;
// Compile the specified LNString text formula into the actual formula.
// Note: The following call is not a C++ call so we need to handle the error return.
if (Error = NSFFormulaCompile( NULL, 0, Formula.GetTextPtr(),
(WORD)Formula.GetByteCount(),
&FormulaHandle, &Wnop, &Werr,
&Wnop, &Wnop,&Wnop,&Wnop ) )
throw Error;
// Get the length of the compiled formula for the button.
// NOTE for C API programmers: The LNCompositeData class will make sure
// that the CD record is aligned on even byte boundaries for you.
if ( Error = NSFFormulaGetSize(FormulaHandle, &Length) )
throw Error;
// Note!!!
// A rich text button consists of 3 CD records:
// - HotspotBegin record
// - Button record
// - HotspotEnd record.
// In order to create a rich text button, we need to create each of those
// records separately.
// Let's start by setting up the CD Hot Spot Begin record.
//
Hotspotbegin.Header.Signature = SIG_CD_HOTSPOTBEGIN;
Hotspotbegin.Header.Length = ( ODSLength(_CDHOTSPOTBEGIN) + Length ); // see: NOTE above.
Hotspotbegin.Type = HOTSPOTREC_TYPE_BUTTON;
Hotspotbegin.Flags = HOTSPOTREC_RUNFLAG_NOBORDER; // See: C API, HOTSPOTREC_RUNFLAG_xxx
Hotspotbegin.DataLength = Length; // Length of the button's compiled formula.
// Write the filled CDHOTSPOTBEGIN record into the LNCompositeData object.
CD.WriteODS(_CDHOTSPOTBEGIN, &Hotspotbegin);
//Get a pointer to the compiled formula's buffer.
FormulaBuf = OSLock(char, FormulaHandle);
// Write the compiled formula data to the CD object.
CD.Write( Length, FormulaBuf, ODSLength(_CDHOTSPOTBEGIN) );
// Unlock it immediately after use.
OSUnlock(FormulaHandle);
// Get rid of the compiled formula, since we don't need it anymore.
if (FormulaHandle)
OSMemFree(FormulaHandle);
// Append this composite data object to the end of the rich text field.
RT->Append(CD);
// Get the Length of the button's title string.
// NOTE for C API programmers: The LNCompositeData class will make sure
// that the CD record is aligned on even byte boundaries for you.
Length = (WORD)ButtonTitle.GetByteCount();
//
// Set up the CD Button data structure.
//
Button.Header.Signature = SIG_CD_BUTTON;
Button.Header.Length = ( ODSLength(_CDBUTTON) + Length ); // see: NOTE above.
Button.Flags = NULL;
Button.Width = (ONEINCH * 2);
Button.Height = NULL;
Button.Lines = 5;
Button.FontID = DEFAULT_FONT_ID;
// Write the filled CDButton record into the LNCompositeData object.
CD.WriteODS(_CDBUTTON, &Button);
// Write the button title text after the CDButton record info.
CD.Write( Length, ButtonTitle.GetTextPtr(), ODSLength(_CDBUTTON) );
// Append this composite data object to the end of the rich text field.
RT->Append (CD);
//
// Set up the CD Hotspot End data structure.
//
Hotspotend.Header.Signature = SIG_CD_HOTSPOTEND;
Hotspotend.Header.Length = (BYTE)ODSLength(_CDHOTSPOTEND);
// Write the filled CDHOTSPOTEND record into the LNCompositeData object.
CD.WriteODS(_CDHOTSPOTEND, &Hotspotend);
// Append this composite data object to the end of the rich text field.
RT->Append (CD);
RT->Append(" "); // Add a space after the button records.
RT->Append("\n\n");
} // END AppendCDButton()
//---------------------------------------------------------------------------
// Name:
// EditCDButtonLabel
//
// Description:
// Set the button label to the new label (passed in), using CD records.
//
//---------------------------------------------------------------------------
void EditCDButtonLabel (LNString NewLabel, LNRichText *RT)
{
LNINT NewLength;
CDBUTTON Button;
LNINT Counter;
LNCompositeData CD;
LNRTCursor Cursor;
LNSTATUS Lnstatus;
WORD CDSig;
// Modify the second button stored as a CD record
// Initialize the counter - we need the SECOND button to modify.
Counter = 0;
// Get a cursor at the start of all the rich text
RT->GetCursor(&Cursor);
// Find the first composite data object
Lnstatus = Cursor.GotoFirst(LNRTTYPE_COMPOSITE_DATA, &CD);
if (Lnstatus != LNWARN_NOT_FOUND)
{
while (Counter != 2)
{
// Get the signature from the composite object
CDSig = CD.GetCDSignature();
if (CDSig == SIG_CD_BUTTON) // IF found a button...
Counter++;
if (Counter == 2) // ...and it's the second one
{
// In order to change the label of the button,
// we need to first read the data structure, then modify it,
// and finally write it back.
CD.ReadODS(_CDBUTTON, &Button);
// Calculate the length of the new label and adjust the header length
// appropriately
NewLength = (NewLabel.GetByteCount());
Button.Header.Length = (WORD)( ODSLength(_CDBUTTON) + NewLength );
// Write the CDButton record into the LNCompositeData object.
CD.WriteODS(_CDBUTTON, &Button);
// Write the button title text after the CDButton record info.
CD.Write( NewLength, NewLabel.GetTextPtr(), ODSLength(_CDBUTTON));
}
// Otherwise, we have to look for more composite data records
Lnstatus = Cursor.GotoNext(LNRTTYPE_COMPOSITE_DATA, &CD);
if (Lnstatus == LNWARN_NOT_FOUND) // There are no more composite data records left.
{
cout << "Error, button not found." << endl;
break;
}
}
}
else
cout << "Error, no Composite Data objects found." << endl;
} // END EditCDButtonLabel()
//---------------------------------------------------------------------------
// Name:
// DeleteButton
//
// Description:
// Removes the button from the document
//
//---------------------------------------------------------------------------
void DeleteButton (LNDocument *CurDoc, LNButton *Button)
{
LNRichText RT;
CurDoc->GetItem("Body", &RT);
RT.Delete(Button);
} // END DeleteButton()
//---------------------------------------------------------------------------
// Name:
// DeleteCDButton
//
// Description:
// Removes the button from the document using CD records.
//
//---------------------------------------------------------------------------
void DeleteCDButton(LNRichText *RT)
{
LNRTCursor Cursor;
LNCompositeData CDHotspotBegin, CDButton, CDHotspotEnd;
LNINT HotspotBeginCounter=0;
LNSTATUS Lnstatus;
WORD CDSig;
LNBOOL NotFound=FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -